opal 0.3.18 → 0.3.19

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 (259) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +1 -3
  3. data/README.md +472 -10
  4. data/Rakefile +10 -52
  5. data/core/array.rb +9 -14
  6. data/core/basic_object.rb +7 -10
  7. data/core/boolean.rb +5 -1
  8. data/core/class.rb +15 -38
  9. data/core/dir.rb +89 -0
  10. data/core/enumerable.rb +133 -57
  11. data/core/error.rb +15 -1
  12. data/core/file.rb +85 -0
  13. data/core/hash.rb +186 -32
  14. data/core/kernel.rb +30 -31
  15. data/core/load_order +4 -2
  16. data/core/module.rb +42 -62
  17. data/core/numeric.rb +7 -1
  18. data/core/object.rb +1 -1
  19. data/core/proc.rb +6 -2
  20. data/core/range.rb +16 -28
  21. data/core/regexp.rb +3 -3
  22. data/core/runtime.js +281 -350
  23. data/core/string.rb +100 -110
  24. data/docs/CNAME +1 -0
  25. data/docs/Rakefile +55 -0
  26. data/docs/css/styles.css +50 -0
  27. data/docs/css/syntax.css +63 -0
  28. data/docs/layout/post.html +3 -0
  29. data/docs/layout/pre.html +11 -0
  30. data/examples/dependencies/app.rb +3 -0
  31. data/lib/opal.rb +2 -1
  32. data/lib/opal/builder.rb +36 -10
  33. data/lib/opal/builder_task.rb +51 -24
  34. data/lib/opal/grammar.rb +2509 -2439
  35. data/lib/opal/grammar.y +38 -5
  36. data/lib/opal/lexer.rb +18 -2
  37. data/lib/opal/parser.rb +375 -349
  38. data/lib/opal/scope.rb +24 -2
  39. data/lib/opal/version.rb +1 -1
  40. data/spec/builder/build_order_spec.rb +20 -0
  41. data/spec/builder/lib_name_for_spec.rb +24 -0
  42. data/spec/grammar/call_spec.rb +9 -6
  43. data/spec/grammar/lambda_spec.rb +64 -0
  44. data/spec/grammar/sclass_spec.rb +5 -3
  45. data/{core/spec → test}/core/array/allocate_spec.rb +0 -0
  46. data/{core/spec → test}/core/array/append_spec.rb +0 -0
  47. data/{core/spec → test}/core/array/assoc_spec.rb +0 -0
  48. data/{core/spec → test}/core/array/at_spec.rb +0 -0
  49. data/{core/spec → test}/core/array/clear_spec.rb +0 -0
  50. data/{core/spec → test}/core/array/clone_spec.rb +0 -0
  51. data/{core/spec → test}/core/array/collect_spec.rb +0 -0
  52. data/{core/spec → test}/core/array/compact_spec.rb +0 -0
  53. data/{core/spec → test}/core/array/concat_spec.rb +0 -0
  54. data/{core/spec → test}/core/array/constructor_spec.rb +0 -0
  55. data/{core/spec → test}/core/array/count_spec.rb +0 -0
  56. data/{core/spec → test}/core/array/delete_at_spec.rb +0 -0
  57. data/{core/spec → test}/core/array/delete_if_spec.rb +0 -0
  58. data/{core/spec → test}/core/array/delete_spec.rb +0 -0
  59. data/{core/spec → test}/core/array/each_index_spec.rb +0 -0
  60. data/{core/spec → test}/core/array/each_spec.rb +0 -0
  61. data/{core/spec → test}/core/array/element_reference_spec.rb +0 -0
  62. data/{core/spec → test}/core/array/empty_spec.rb +0 -0
  63. data/{core/spec → test}/core/array/eql_spec.rb +0 -0
  64. data/{core/spec → test}/core/array/fetch_spec.rb +0 -0
  65. data/{core/spec → test}/core/array/first_spec.rb +0 -0
  66. data/{core/spec → test}/core/array/flatten_spec.rb +0 -0
  67. data/{core/spec → test}/core/array/include_spec.rb +0 -0
  68. data/{core/spec → test}/core/array/insert_spec.rb +0 -0
  69. data/{core/spec → test}/core/array/last_spec.rb +0 -0
  70. data/{core/spec → test}/core/array/length_spec.rb +0 -0
  71. data/{core/spec → test}/core/array/map_spec.rb +0 -0
  72. data/{core/spec → test}/core/array/plus_spec.rb +0 -0
  73. data/{core/spec → test}/core/array/pop_spec.rb +0 -0
  74. data/{core/spec → test}/core/array/push_spec.rb +0 -0
  75. data/{core/spec → test}/core/array/rassoc_spec.rb +0 -0
  76. data/{core/spec → test}/core/array/reject_spec.rb +0 -0
  77. data/{core/spec → test}/core/array/replace_spec.rb +0 -0
  78. data/{core/spec → test}/core/array/reverse_each_spec.rb +0 -0
  79. data/{core/spec → test}/core/array/reverse_spec.rb +0 -0
  80. data/{core/spec → test}/core/array/size_spec.rb +0 -0
  81. data/{core/spec → test}/core/array/to_ary_spec.rb +0 -0
  82. data/{core/spec → test}/core/array/uniq_spec.rb +0 -0
  83. data/{core/spec → test}/core/array/zip_spec.rb +0 -0
  84. data/test/core/class/fixtures/classes.rb +9 -0
  85. data/test/core/class/new_spec.rb +108 -0
  86. data/{core/spec → test}/core/enumerable/all_spec.rb +0 -0
  87. data/{core/spec → test}/core/enumerable/any_spec.rb +0 -0
  88. data/{core/spec → test}/core/enumerable/collect_spec.rb +0 -0
  89. data/{core/spec → test}/core/enumerable/count_spec.rb +0 -0
  90. data/test/core/enumerable/detect_spec.rb +48 -0
  91. data/test/core/enumerable/drop_spec.rb +17 -0
  92. data/test/core/enumerable/drop_while_spec.rb +24 -0
  93. data/test/core/enumerable/each_with_index_spec.rb +11 -0
  94. data/test/core/enumerable/each_with_object_spec.rb +17 -0
  95. data/test/core/enumerable/entries_spec.rb +6 -0
  96. data/test/core/enumerable/find_all_spec.rb +13 -0
  97. data/test/core/enumerable/find_index_spec.rb +45 -0
  98. data/test/core/enumerable/find_spec.rb +48 -0
  99. data/test/core/enumerable/first_spec.rb +40 -0
  100. data/{core/spec → test}/core/enumerable/fixtures/classes.rb +19 -0
  101. data/test/core/enumerable/grep_spec.rb +21 -0
  102. data/test/core/enumerable/take_spec.rb +40 -0
  103. data/test/core/enumerable/to_a_spec.rb +6 -0
  104. data/{core/spec → test}/core/false/and_spec.rb +0 -0
  105. data/{core/spec → test}/core/false/inspect_spec.rb +0 -0
  106. data/{core/spec → test}/core/false/or_spec.rb +0 -0
  107. data/{core/spec → test}/core/false/to_s_spec.rb +0 -0
  108. data/{core/spec → test}/core/false/xor_spec.rb +0 -0
  109. data/test/core/file/expand_path_spec.rb +20 -0
  110. data/{core/spec → test}/core/hash/allocate_spec.rb +0 -0
  111. data/{core/spec → test}/core/hash/assoc_spec.rb +0 -0
  112. data/{core/spec → test}/core/hash/clear_spec.rb +0 -0
  113. data/{core/spec → test}/core/hash/clone_spec.rb +0 -0
  114. data/test/core/hash/default_spec.rb +9 -0
  115. data/{core/spec → test}/core/hash/delete_if_spec.rb +0 -0
  116. data/test/core/hash/each_key_spec.rb +15 -0
  117. data/test/core/hash/each_pair_spec.rb +30 -0
  118. data/test/core/hash/each_spec.rb +30 -0
  119. data/test/core/hash/each_value_spec.rb +15 -0
  120. data/{core/spec → test}/core/hash/element_reference_spec.rb +14 -0
  121. data/{core/spec → test}/core/hash/element_set_spec.rb +1 -0
  122. data/test/core/hash/empty_spec.rb +10 -0
  123. data/test/core/hash/fetch_spec.rb +24 -0
  124. data/test/core/hash/flatten_spec.rb +46 -0
  125. data/test/core/hash/has_key_spec.rb +24 -0
  126. data/test/core/hash/has_value_spec.rb +12 -0
  127. data/test/core/hash/include_spec.rb +24 -0
  128. data/test/core/hash/index_spec.rb +13 -0
  129. data/test/core/hash/indexes_spec.rb +9 -0
  130. data/test/core/hash/indices_spec.rb +9 -0
  131. data/test/core/hash/invert_spec.rb +12 -0
  132. data/test/core/hash/keep_if_spec.rb +18 -0
  133. data/test/core/hash/key_spec.rb +24 -0
  134. data/test/core/hash/keys_spec.rb +10 -0
  135. data/test/core/hash/length_spec.rb +10 -0
  136. data/test/core/hash/member_spec.rb +24 -0
  137. data/{core/spec → test}/core/hash/merge_spec.rb +0 -0
  138. data/{core/spec → test}/core/hash/new_spec.rb +0 -0
  139. data/test/core/hash/rassoc_spec.rb +34 -0
  140. data/test/core/hash/replace_spec.rb +7 -0
  141. data/test/core/hash/select_spec.rb +52 -0
  142. data/test/core/hash/shift_spec.rb +19 -0
  143. data/test/core/hash/size_spec.rb +10 -0
  144. data/test/core/hash/update_spec.rb +17 -0
  145. data/test/core/hash/value_spec.rb +12 -0
  146. data/test/core/hash/values_at_spec.rb +9 -0
  147. data/test/core/hash/values_spec.rb +7 -0
  148. data/test/core/kernel/eql_spec.rb +15 -0
  149. data/test/core/kernel/equal_value_spec.rb +12 -0
  150. data/test/core/kernel/loop_spec.rb +23 -0
  151. data/test/core/kernel/nil_spec.rb +7 -0
  152. data/test/core/kernel/proc_spec.rb +9 -0
  153. data/test/core/kernel/rand_spec.rb +14 -0
  154. data/test/core/kernel/respond_to_spec.rb +24 -0
  155. data/test/core/kernel/send_spec.rb +56 -0
  156. data/test/core/kernel/tap_spec.rb +10 -0
  157. data/test/core/kernel/to_s_spec.rb +5 -0
  158. data/{core/spec → test}/core/matchdata/to_a_spec.rb +0 -0
  159. data/{core/spec → test}/core/nil/and_spec.rb +0 -0
  160. data/{core/spec → test}/core/nil/inspect_spec.rb +0 -0
  161. data/{core/spec → test}/core/nil/nil_spec.rb +0 -0
  162. data/{core/spec → test}/core/nil/or_spec.rb +0 -0
  163. data/{core/spec → test}/core/nil/to_a_spec.rb +0 -0
  164. data/{core/spec → test}/core/nil/to_f_spec.rb +0 -0
  165. data/{core/spec → test}/core/nil/to_i_spec.rb +0 -0
  166. data/{core/spec → test}/core/nil/to_s_spec.rb +0 -0
  167. data/{core/spec → test}/core/nil/xor_spec.rb +0 -0
  168. data/{core/spec → test}/core/numeric/equal_value_spec.rb +0 -0
  169. data/test/core/range/begin_spec.rb +9 -0
  170. data/test/core/range/case_compare_spec.rb +16 -0
  171. data/test/core/range/end_spec.rb +9 -0
  172. data/{core/spec → test}/core/regexp/match_spec.rb +0 -0
  173. data/test/core/string/capitalize_spec.rb +10 -0
  174. data/test/core/string/casecmp_spec.rb +16 -0
  175. data/test/core/string/chomp_spec.rb +43 -0
  176. data/test/core/string/chop_spec.rb +10 -0
  177. data/test/core/string/chr_spec.rb +13 -0
  178. data/test/core/string/comparison_spec.rb +13 -0
  179. data/test/core/string/downcase_spec.rb +6 -0
  180. data/test/core/string/element_reference_spec.rb +72 -0
  181. data/test/core/string/empty_spec.rb +8 -0
  182. data/test/core/string/end_with_spec.rb +12 -0
  183. data/test/core/string/fixtures/classes.rb +3 -0
  184. data/test/core/string/gsub_spec.rb +17 -0
  185. data/test/core/string/include_spec.rb +12 -0
  186. data/test/core/string/intern_spec.rb +9 -0
  187. data/test/core/string/length_spec.rb +9 -0
  188. data/test/core/string/lstrip_spec.rb +7 -0
  189. data/test/core/string/match_spec.rb +27 -0
  190. data/test/core/string/next_spec.rb +10 -0
  191. data/test/core/string/ord_spec.rb +9 -0
  192. data/test/core/string/partition_spec.rb +10 -0
  193. data/test/core/string/reverse_spec.rb +7 -0
  194. data/test/core/string/rstrip_spec.rb +7 -0
  195. data/test/core/string/size_spec.rb +9 -0
  196. data/test/core/string/slice_spec.rb +72 -0
  197. data/test/core/string/split_spec.rb +5 -0
  198. data/test/core/string/start_with_spec.rb +12 -0
  199. data/test/core/string/strip_spec.rb +6 -0
  200. data/test/core/string/sub_spec.rb +22 -0
  201. data/test/core/string/succ_spec.rb +10 -0
  202. data/test/core/string/sum_spec.rb +5 -0
  203. data/test/core/string/swapcase_spec.rb +18 -0
  204. data/test/core/string/to_a_spec.rb +9 -0
  205. data/test/core/string/to_f_spec.rb +14 -0
  206. data/test/core/string/to_i_spec.rb +25 -0
  207. data/test/core/string/to_s_spec.rb +13 -0
  208. data/test/core/string/to_str_spec.rb +13 -0
  209. data/test/core/string/to_sym_spec.rb +9 -0
  210. data/test/core/string/upcase_spec.rb +6 -0
  211. data/test/core/symbol/to_proc_spec.rb +12 -0
  212. data/{core/spec → test}/core/true/and_spec.rb +0 -0
  213. data/{core/spec → test}/core/true/inspect_spec.rb +0 -0
  214. data/{core/spec → test}/core/true/or_spec.rb +0 -0
  215. data/{core/spec → test}/core/true/to_s_spec.rb +0 -0
  216. data/{core/spec → test}/core/true/xor_spec.rb +0 -0
  217. data/test/index.html +11 -0
  218. data/{core/spec → test}/language/alias_spec.rb +4 -0
  219. data/{core/spec → test}/language/and_spec.rb +0 -0
  220. data/{core/spec → test}/language/array_spec.rb +0 -0
  221. data/{core/spec → test}/language/block_spec.rb +0 -0
  222. data/{core/spec → test}/language/break_spec.rb +0 -0
  223. data/{core/spec → test}/language/case_spec.rb +0 -0
  224. data/{core/spec → test}/language/defined_spec.rb +0 -0
  225. data/{core/spec → test}/language/ensure_spec.rb +0 -0
  226. data/test/language/fixtures/yield.rb +23 -0
  227. data/{core/spec → test}/language/hash_spec.rb +0 -0
  228. data/{core/spec → test}/language/if_spec.rb +0 -0
  229. data/test/language/literal_lambda_spec.rb +47 -0
  230. data/{core/spec → test}/language/loop_spec.rb +0 -0
  231. data/{core/spec → test}/language/metaclass_spec.rb +0 -0
  232. data/{core/spec → test}/language/next_spec.rb +0 -0
  233. data/{core/spec → test}/language/or_spec.rb +0 -0
  234. data/{core/spec → test}/language/predefined_spec.rb +0 -0
  235. data/{core/spec → test}/language/regexp_spec.rb +0 -0
  236. data/{core/spec → test}/language/send_spec.rb +0 -0
  237. data/{core/spec → test}/language/singleton_class_spec.rb +0 -0
  238. data/{core/spec → test}/language/super_spec.rb +0 -0
  239. data/{core/spec → test}/language/symbol_spec.rb +0 -0
  240. data/{core/spec → test}/language/undef_spec.rb +0 -0
  241. data/{core/spec → test}/language/unless_spec.rb +0 -0
  242. data/{core/spec → test}/language/until_spec.rb +0 -0
  243. data/{core/spec → test}/language/variables_spec.rb +0 -0
  244. data/{core/spec → test}/language/while_spec.rb +0 -0
  245. data/test/language/yield_spec.rb +100 -0
  246. data/test/opal/array/subclassing_spec.rb +32 -0
  247. data/test/opal/class/bridge_class_spec.rb +37 -0
  248. data/test/opal/exception/subclassing_spec.rb +17 -0
  249. data/test/opal/runtime/_methods_spec.rb +48 -0
  250. data/test/opal/runtime/class_hierarchy_spec.rb +22 -0
  251. data/test/opal/runtime/def_spec.rb +23 -0
  252. data/test/opal/string/subclassing_spec.rb +26 -0
  253. data/test/spec_helper.rb +3 -0
  254. metadata +437 -111
  255. data/core/spec/core/class/new_spec.rb +0 -16
  256. data/core/spec/core/hash/default_spec.rb +0 -4
  257. data/core/spec/core/symbol/to_proc_spec.rb +0 -6
  258. data/core/spec/index.html +0 -11
  259. data/spec/builder/build_source_spec.rb +0 -52
@@ -1,4 +1,4 @@
1
- class Regexp
1
+ class Regexp < `RegExp`
2
2
  def self.escape(string)
3
3
  `string.replace(/([.*+?^=!:${}()|[\]\\/\\])/g, '\\$1')`
4
4
  end
@@ -20,7 +20,7 @@ class Regexp
20
20
  var result = this.exec(string);
21
21
 
22
22
  if (result) {
23
- var match = new RubyMatch._alloc();
23
+ var match = new #{MatchData}._alloc();
24
24
  match.$data = result;
25
25
 
26
26
  #{$~ = `match`};
@@ -44,7 +44,7 @@ class Regexp
44
44
  var result = this.exec(pattern);
45
45
 
46
46
  if (result) {
47
- var match = new RubyMatch._alloc();
47
+ var match = new #{MatchData}._alloc();
48
48
  match.$data = result;
49
49
 
50
50
  return #{$~ = `match`};
@@ -1,243 +1,134 @@
1
- var Opal = this.Opal = {};
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;
5
+
6
+ var Opal = this.Opal = top_const_scope;
2
7
 
3
8
  Opal.global = this;
4
9
 
5
10
  // Minify common function calls
6
- var __hasOwn = Object.prototype.hasOwnProperty,
7
- __slice = Array.prototype.slice;
8
-
9
- // Types - also added to bridged objects
10
- var T_CLASS = 0x0001,
11
- T_MODULE = 0x0002,
12
- T_OBJECT = 0x0004,
13
- T_BOOLEAN = 0x0008,
14
- T_STRING = 0x0010,
15
- T_ARRAY = 0x0020,
16
- T_NUMBER = 0x0040,
17
- T_PROC = 0x0080,
18
- T_HASH = 0x0100,
19
- T_RANGE = 0x0200,
20
- T_ICLASS = 0x0400,
21
- FL_SINGLETON = 0x0800;
11
+ var __hasOwn = Object.prototype.hasOwnProperty;
12
+ var __slice = Opal.slice = Array.prototype.slice;
22
13
 
23
14
  // Generates unique id for every ruby object
24
15
  var unique_id = 0;
25
16
 
26
- // Jump return - return in proc body
27
- Opal.jump = function(value, func) {
28
- throw new Error('jump return');
29
- };
30
-
31
- // Get constant with given id
32
- Opal.const_get = function(const_table, id) {
33
- if (const_table[id]) {
34
- return const_table[id];
35
- }
36
-
37
- throw RubyNameError.$new('uninitialized constant ' + id);
38
- };
39
-
40
17
  // Table holds all class variables
41
18
  Opal.cvars = {};
42
19
 
43
20
  // Globals table
44
21
  Opal.gvars = {};
45
22
 
46
- // Define a method alias
47
- Opal.alias = function(klass, new_name, old_name) {
48
- new_name = mid_to_jsid(new_name);
49
- old_name = mid_to_jsid(old_name);
50
-
51
- var body = klass._proto[old_name];
52
-
53
- if (!body) {
54
- // throw RubyNameError.$new(null, "undefined method `" + old_name + "' for class `" + klass._name + "'");
55
- throw new Error("undefined method `" + old_name + "' for class `" + klass._name + "'");
23
+ Opal.klass = function(base, superklass, id, body) {
24
+ var klass;
25
+ if (base._isObject) {
26
+ base = base._real;
56
27
  }
57
28
 
58
- define_method(klass, new_name, body);
59
- return null;
60
- };
61
-
62
- // Actually define methods
63
- var define_method = Opal.defn = function(klass, id, body) {
64
- // If an object, make sure to use its class
65
- if (klass._flags & T_OBJECT) {
66
- klass = klass._klass;
29
+ if (superklass === null) {
30
+ superklass = RubyObject;
67
31
  }
68
32
 
69
- klass._alloc.prototype[id] = body;
70
-
71
- var included_in = klass.$included_in, includee;
72
-
73
- if (included_in) {
74
- for (var i = 0, ii = included_in.length; i < ii; i++) {
75
- includee = included_in[i];
76
-
77
- define_method(includee, id, body);
78
- }
33
+ if (__hasOwn.call(base._scope, id)) {
34
+ klass = base._scope[id];
79
35
  }
80
-
81
- if (klass._bridge) {
82
- klass._bridge[id] = body;
36
+ else if (!superklass._klass || !superklass._proto) {
37
+ klass = bridge_class(superklass, id);
83
38
  }
84
-
85
-
86
- return null;
87
- }
88
-
89
- function define_module(base, id) {
90
- var module;
91
-
92
- module = boot_module();
93
- module._name = (base === RubyObject ? id : base._name + '::' + id)
94
-
95
- make_metaclass(module, RubyModule);
96
-
97
- module._flags = T_MODULE;
98
- module.$included_in = [];
99
-
100
- var const_alloc = function() {};
101
- var const_scope = const_alloc.prototype = new base._scope.alloc();
102
- module._scope = const_scope;
103
- const_scope.alloc = const_alloc;
104
-
105
- base._scope[id] = module;
106
-
107
- return module;
108
- }
109
-
110
- // Opal define class. 0: regular, 1: module, 2: shift class.
111
- Opal.klass = function(base, superklass, id, body, type) {
112
- var klass;
113
-
114
- switch (type) {
115
- case 0:
116
- if (base._flags & T_OBJECT) {
117
- base = class_real(base._klass);
118
- }
119
-
120
- if (superklass === null) {
121
- superklass = RubyObject;
122
- }
123
-
124
- if (__hasOwn.call(base._scope, id)) {
125
- klass = base._scope[id];
126
- }
127
- else {
128
- klass = define_class(base, id, superklass);
129
- }
130
-
131
- break;
132
-
133
- case 1:
134
- if (base._flags & T_OBJECT) {
135
- base = class_real(base._klass);
136
- }
137
-
138
- if (__hasOwn.call(base._scope, id)) {
139
- klass = base._scope[id];
140
- }
141
- else {
142
- klass = define_module(base, id);
143
- }
144
-
145
- break;
146
-
147
- case 2:
148
- klass = base.$singleton_class();
149
- break;
39
+ else {
40
+ klass = define_class(base, id, superklass);
150
41
  }
151
42
 
152
43
  return body.call(klass);
153
44
  };
154
45
 
155
- Opal.slice = __slice;
156
-
157
- Opal.defs = function(base, id, body) {
158
- return define_method(base.$singleton_class(), id, body);
159
- };
160
-
161
- // Undefine one or more methods
162
- Opal.undef = function(klass) {
163
- var args = __slice.call(arguments, 1);
164
-
165
- for (var i = 0, length = args.length; i < length; i++) {
166
- var mid = args[i], id = mid_to_jsid[mid];
46
+ Opal.sklass = function(shift, body) {
47
+ var klass = shift.$singleton_class();
48
+ return body.call(klass);
49
+ }
167
50
 
168
- delete klass._proto[id];
51
+ Opal.module = function(base, id, body) {
52
+ var klass;
53
+ if (base._isObject) {
54
+ base = base._real;
169
55
  }
170
- };
171
56
 
172
- // Calls a super method.
173
- Opal.zuper = function(callee, jsid, self, args) {
174
- var func = find_super(self._klass, callee, jsid);
175
-
176
- if (!func) {
177
- throw RubyNoMethodError.$new(null, "super: no superclass method `" +
178
- jsid_to_mid(jsid) + "'" + " for " + self.$inspect());
57
+ if (__hasOwn.call(base._scope, id)) {
58
+ klass = base._scope[id];
179
59
  }
60
+ else {
61
+ klass = boot_module();
62
+ klass._name = (base === RubyObject ? id : base._name + '::' + id);
180
63
 
181
- return func.apply(self, args);
182
- };
64
+ make_metaclass(klass, RubyModule);
183
65
 
184
- // dynamic super (inside block)
185
- Opal.dsuper = function(scopes, defn, jsid, self, args) {
186
- var method, scope = scopes[0];
66
+ klass._isModule = true;
67
+ klass.$included_in = [];
187
68
 
188
- for (var i = 0, length = scopes.length; i < length; i++) {
189
- if (scope.o$jsid) {
190
- jsid = scope.o$jsid;
191
- method = scope;
192
- break;
193
- }
194
- }
69
+ var const_alloc = function() {};
70
+ var const_scope = const_alloc.prototype = new base._scope.alloc();
71
+ klass._scope = const_scope;
72
+ const_scope.alloc = const_alloc;
195
73
 
196
- if (method) {
197
- // one of the nested blocks was define_method'd
198
- return Opal.zuper(method, jsid, self, args);
199
- }
200
- else if (defn) {
201
- // blocks not define_method'd, but they were enclosed by a real method
202
- return Opal.zuper(defn, jsid, self, args);
74
+ base._scope[id] = klass;
203
75
  }
204
76
 
205
- // if we get here then we were inside a nest of just blocks, and none have
206
- // been defined as a method
207
- throw RubyNoMethodError.$new(null, "super: cannot call super when not in method");
77
+ return body.call(klass);
208
78
  }
209
79
 
210
- // Find function body for the super call
211
- function find_super(klass, callee, mid) {
212
- var cur_method;
213
-
214
- while (klass) {
215
- if (klass._proto.hasOwnProperty(mid)) {
216
- if (klass._proto[mid] === callee) {
217
- cur_method = klass._proto[mid];
218
- break;
219
- }
220
- }
221
- klass = klass._super;
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);
222
114
  }
223
115
 
224
- if (!(klass && cur_method)) { return null; }
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;
225
120
 
226
- klass = klass._super;
121
+ for (var j = 0, jj = methods.length; j < jj; j++) {
122
+ method = methods[j];
123
+ dest[method] = table[method];
124
+ }
227
125
 
228
- while (klass) {
229
- if (klass._proto.hasOwnProperty(mid)) {
230
- // make sure our found method isnt the same - this can happen if this
231
- // newly found method is from a module and we are now looking at the
232
- // module it came from.
233
- if (klass._proto[mid] !== callee) {
234
- return klass._proto[mid];
126
+ if (includee.$included_in) {
127
+ Opal.donate(includee, methods, true);
235
128
  }
236
129
  }
237
-
238
- klass = klass._super;
239
130
  }
240
- }
131
+ };
241
132
 
242
133
  var mid_to_jsid = Opal.mid_to_jsid = function(mid) {
243
134
  if (method_names[mid]) {
@@ -245,7 +136,7 @@ var mid_to_jsid = Opal.mid_to_jsid = function(mid) {
245
136
  }
246
137
 
247
138
  return '$' + mid.replace('!', '$b').replace('?', '$p').replace('=', '$e');
248
- }
139
+ };
249
140
 
250
141
  var jsid_to_mid = Opal.jsid_to_mid = function(jsid) {
251
142
  if (reverse_method_names[jsid]) {
@@ -255,18 +146,16 @@ var jsid_to_mid = Opal.jsid_to_mid = function(jsid) {
255
146
  jsid = jsid.substr(1); // remove '$'
256
147
 
257
148
  return jsid.replace('$b', '!').replace('$p', '?').replace('$e', '=');
258
- }
149
+ };
259
150
 
260
- Opal.arg_error = function(given, expected) {
261
- throw RubyArgError.$new(null, 'wrong number of arguments(' + given + ' for ' + expected + ')');
151
+ var no_block_given = function() {
152
+ throw new Error('no block given');
262
153
  };
263
154
 
264
155
  // Boot a base class (makes instances).
265
156
  function boot_defclass(superklass) {
266
157
  var cls = function() {
267
158
  this._id = unique_id++;
268
-
269
- return this;
270
159
  };
271
160
 
272
161
  if (superklass) {
@@ -277,7 +166,7 @@ function boot_defclass(superklass) {
277
166
  }
278
167
 
279
168
  cls.prototype.constructor = cls;
280
- cls.prototype._flags = T_OBJECT;
169
+ cls.prototype._isObject = true;
281
170
 
282
171
  return cls;
283
172
  }
@@ -286,8 +175,6 @@ function boot_defclass(superklass) {
286
175
  function boot_makemeta(id, klass, superklass) {
287
176
  var meta = function() {
288
177
  this._id = unique_id++;
289
-
290
- return this;
291
178
  };
292
179
 
293
180
  var ctor = function() {};
@@ -297,16 +184,22 @@ function boot_makemeta(id, klass, superklass) {
297
184
 
298
185
  var proto = meta.prototype;
299
186
  proto.$included_in = [];
300
- proto._alloc = klass;
301
- proto._flags = T_CLASS;
302
- proto._name = id;
303
- proto._super = superklass;
187
+ proto._alloc = klass;
188
+ proto._isClass = true;
189
+ proto._name = id;
190
+ proto._super = superklass;
304
191
  proto.constructor = meta;
192
+ proto._methods = [];
193
+ proto._isObject = false;
305
194
 
306
195
  var result = new meta();
307
196
  klass.prototype._klass = result;
197
+ klass.prototype._real = result;
198
+
308
199
  result._proto = klass.prototype;
309
200
 
201
+ top_const_scope[id] = result;
202
+
310
203
  return result;
311
204
  }
312
205
 
@@ -315,8 +208,6 @@ function boot_class(superklass) {
315
208
  // instances
316
209
  var cls = function() {
317
210
  this._id = unique_id++;
318
-
319
- return this;
320
211
  };
321
212
 
322
213
  var ctor = function() {};
@@ -326,13 +217,11 @@ function boot_class(superklass) {
326
217
 
327
218
  var proto = cls.prototype;
328
219
  proto.constructor = cls;
329
- proto._flags = T_OBJECT;
220
+ proto._isObject = true;
330
221
 
331
222
  // class itself
332
223
  var meta = function() {
333
224
  this._id = unique_id++;
334
-
335
- return this;
336
225
  };
337
226
 
338
227
  var mtor = function() {};
@@ -340,14 +229,16 @@ function boot_class(superklass) {
340
229
 
341
230
  meta.prototype = new mtor();
342
231
 
343
- proto = meta.prototype;
344
- proto._alloc = cls;
345
- proto._flags = T_CLASS;
346
- proto.constructor = meta;
347
- proto._super = superklass;
232
+ proto = meta.prototype;
233
+ proto._alloc = cls;
234
+ proto._isClass = true;
235
+ proto.constructor = meta;
236
+ proto._super = superklass;
237
+ proto._methods = [];
348
238
 
349
239
  var result = new meta();
350
240
  cls.prototype._klass = result;
241
+ cls.prototype._real = result;
351
242
 
352
243
  result._proto = cls.prototype;
353
244
 
@@ -363,7 +254,6 @@ function boot_module() {
363
254
  // Module itself
364
255
  var meta = function() {
365
256
  this._id = unique_id++;
366
- return this;
367
257
  };
368
258
 
369
259
  var mtor = function(){};
@@ -371,30 +261,23 @@ function boot_module() {
371
261
  meta.prototype = new mtor();
372
262
 
373
263
  var proto = meta.prototype;
374
- proto._alloc = module_cons;
375
- proto._flags = T_MODULE;
264
+
265
+ proto._alloc = module_cons;
266
+ proto._isModule = true;
376
267
  proto.constructor = meta;
377
- proto._super = null;
268
+ proto._super = null;
269
+ proto._methods = [];
378
270
 
379
- var module = new meta();
380
- module._proto = module_inst;
271
+ var module = new meta();
272
+ module._proto = module_inst;
381
273
 
382
274
  return module;
383
275
  }
384
276
 
385
- // Get actual class ignoring singleton classes and iclasses.
386
- function class_real(klass) {
387
- while (klass._flags & FL_SINGLETON) {
388
- klass = klass._super;
389
- }
390
-
391
- return klass;
392
- }
393
-
394
277
  // Make metaclass for the given class
395
278
  function make_metaclass(klass, superklass) {
396
- if (klass._flags & T_CLASS) {
397
- if ((klass._flags & T_CLASS) && (klass._flags & FL_SINGLETON)) {
279
+ if (klass._isClass) {
280
+ if (klass._isSingleton) {
398
281
  throw RubyException.$new('too much meta: return klass?');
399
282
  }
400
283
  else {
@@ -404,8 +287,9 @@ function make_metaclass(klass, superklass) {
404
287
  meta._name = class_id;
405
288
  meta._alloc.prototype = klass.constructor.prototype;
406
289
  meta._proto = meta._alloc.prototype;
407
- meta._flags |= FL_SINGLETON;
290
+ meta._isSingleton = true;
408
291
  meta._klass = RubyClass;
292
+ meta._real = RubyClass;
409
293
 
410
294
  klass._klass = meta;
411
295
 
@@ -416,30 +300,25 @@ function make_metaclass(klass, superklass) {
416
300
  }
417
301
  }
418
302
  else {
419
- return make_singleton_class(klass);
420
- }
421
- }
422
-
423
- function make_singleton_class(obj) {
424
- var orig_class = obj._klass,
425
- class_id = "#<Class:#<" + orig_class._name + ":" + orig_class._id + ">>";
426
-
427
- klass = boot_class(orig_class);
428
- klass._name = class_id;
429
-
430
- klass._flags |= FL_SINGLETON;
431
- klass._bridge = obj;
432
-
433
- obj._klass = klass;
303
+ var orig_class = klass._klass,
304
+ class_id = "#<Class:#<" + orig_class._name + ":" + orig_class._id + ">>";
434
305
 
435
- klass.__attached__ = obj;
306
+ var meta = boot_class(orig_class);
307
+ meta._name = class_id;
436
308
 
437
- klass._klass = class_real(orig_class)._klass;
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
438
316
 
439
- return klass;
317
+ return meta;
318
+ }
440
319
  }
441
320
 
442
- function bridge_class(constructor, flags, id) {
321
+ function bridge_class(constructor, id) {
443
322
  var klass = define_class(RubyObject, id, RubyObject),
444
323
  prototype = constructor.prototype;
445
324
 
@@ -448,20 +327,69 @@ function bridge_class(constructor, flags, id) {
448
327
 
449
328
  bridged_classes.push(klass);
450
329
 
451
- prototype._klass = klass;
452
- prototype._flags = flags;
330
+ prototype._klass = klass;
331
+ prototype._real = klass;
332
+ prototype._isObject = true;
333
+
334
+ var allocator = function(initializer) {
335
+ var result, kls = this, methods = kls._methods, proto = kls._proto;
336
+
337
+ if (initializer == null) {
338
+ result = new constructor
339
+ }
340
+ else {
341
+ result = new constructor(initializer);
342
+ }
343
+
344
+ if (kls === klass) {
345
+ return result;
346
+ }
347
+
348
+ result._klass = kls;
349
+ result._real = kls;
350
+
351
+ for (var i = 0, length = methods.length; i < length; i++) {
352
+ var method = methods[i];
353
+ result[method] = proto[method];
354
+ }
355
+
356
+ return result;
357
+ };
358
+
359
+ klass.constructor.prototype.$allocate = allocator;
360
+
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;
373
+ }
453
374
 
454
375
  return klass;
455
376
  }
456
377
 
457
- // Define new ruby class
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
+ */
458
390
  function define_class(base, id, superklass) {
459
- var klass;
460
-
461
- var class_id = (base === RubyObject ? id : base._name + '::' + id);
462
-
463
- klass = boot_class(superklass);
464
- klass._name = class_id;
391
+ var klass = boot_class(superklass);
392
+ klass._name = (base === RubyObject ? id : base._name + '::' + id);
465
393
 
466
394
  make_metaclass(klass, superklass._klass);
467
395
 
@@ -479,66 +407,118 @@ function define_class(base, id, superklass) {
479
407
  return klass;
480
408
  }
481
409
 
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
+ */
482
423
  function define_iclass(klass, module) {
483
- var sup = klass._super;
484
-
485
- var iclass = {};
486
- iclass._proto = module._proto;
487
- iclass._super = sup;
488
- iclass._flags = T_ICLASS;
489
- iclass._klass = module;
490
- iclass._name = module._name;
424
+ var iclass = {
425
+ _proto: module._proto,
426
+ _super: klass._super,
427
+ _isIClass: true,
428
+ _klass: module,
429
+ _name: module._name,
430
+ _methods: module._methods
431
+ };
491
432
 
492
433
  klass._super = iclass;
493
434
 
494
435
  return iclass;
495
436
  }
496
437
 
497
- // Handling requires
498
- function require_handler(path) {
499
- throw new Error('Cannot require ' + path);
500
- }
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.
441
+
442
+ @type { String: Function }
443
+ */
444
+ var factories = Opal.factories = {};
445
+
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.
450
+
451
+ @type {String}
452
+ */
453
+ Opal.file = "";
454
+
455
+ /**
456
+ Register the body for the given file id name. This will then allow
457
+ the file to be loaded with require().
458
+
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;
464
+ };
465
+
466
+ /**
467
+ Require a specific file by id.
468
+
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];
474
+
475
+ if (!body) {
476
+ throw new Error("No file: '" + id + "'");
477
+ }
478
+
479
+ if (body._loaded) {
480
+ return false;
481
+ }
482
+
483
+ Opal.file = id;
484
+
485
+ body._loaded = true;
486
+ body.call(Opal.top);
487
+
488
+ return true;
489
+ };
501
490
 
502
491
  // Initialization
503
492
  // --------------
504
493
 
505
494
  // The *instances* of core objects
506
- var BootObject = boot_defclass();
507
- var BootModule = boot_defclass(BootObject);
508
- var BootClass = boot_defclass(BootModule);
495
+ var BootBasicObject = boot_defclass();
496
+ var BootObject = boot_defclass(BootBasicObject);
497
+ var BootModule = boot_defclass(BootObject);
498
+ var BootClass = boot_defclass(BootModule);
509
499
 
510
500
  // The *classes' of core objects
511
- var RubyObject = boot_makemeta('Object', BootObject, BootClass);
512
- var RubyModule = boot_makemeta('Module', BootModule, RubyObject.constructor);
513
- var RubyClass = boot_makemeta('Class', BootClass, RubyModule.constructor);
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);
514
505
 
515
506
  // Fix boot classes to use meta class
507
+ RubyBasicObject._klass = RubyClass;
516
508
  RubyObject._klass = RubyClass;
517
509
  RubyModule._klass = RubyClass;
518
510
  RubyClass._klass = RubyClass;
519
511
 
520
512
  // fix superclasses
521
- RubyObject._super = null;
513
+ RubyBasicObject._super = null;
514
+ RubyObject._super = RubyBasicObject;
522
515
  RubyModule._super = RubyObject;
523
516
  RubyClass._super = RubyModule;
524
517
 
525
- Opal.Object = RubyObject;
526
- Opal.Module = RubyModule;
527
- Opal.Class = RubyClass;
528
-
529
- // Make object act like a module. Internally, `Object` gets included
530
- // into all the bridged classes. This is because the native prototypes
531
- // for these bridged classes need to get all the `Object` methods as
532
- // well. This allows `Object` to just donate its instance methods to
533
- // the bridged classes using the exact same method that modules use.
534
518
  var bridged_classes = RubyObject.$included_in = [];
519
+ RubyBasicObject.$included_in = bridged_classes;
535
520
 
536
- // Top level Object scope (used by object and top_self).
537
- var top_const_alloc = function(){};
538
- var top_const_scope = top_const_alloc.prototype;
539
- top_const_scope.alloc = top_const_alloc;
540
-
541
- RubyObject._scope = Opal.constants = top_const_scope;
521
+ RubyObject._scope = RubyBasicObject._scope = top_const_scope;
542
522
 
543
523
  var module_const_alloc = function(){};
544
524
  var module_const_scope = new top_const_alloc();
@@ -550,64 +530,15 @@ var class_const_scope = new top_const_alloc();
550
530
  class_const_scope.alloc = class_const_alloc;
551
531
  RubyClass._scope = class_const_scope;
552
532
 
553
- RubyObject._scope.BasicObject = RubyObject;
554
- RubyObject._scope.Object = RubyObject;
555
- RubyObject._scope.Module = RubyModule;
556
- RubyObject._scope.Class = RubyClass;
557
-
558
- // Every ruby object (except natives) will have their #to_s method aliased
559
- // to the native .toString() function so that accessing ruby objects from
560
- // javascript will return a nicer string format. This is also used when
561
- // interpolating objects into strings as the js engine will call toString
562
- // which in turn calls #to_s.
563
- //
564
- // This is also used as the hashing function. In ruby, #hash should return
565
- // an integer. This is not possible in Opal as strings cannot be mutable
566
- // and can not therefore have unique integer hashes. Seeing as strings or
567
- // symbols are used more often as hash keys, this role is changed in Opal
568
- // so that hash values should be strings, and this function makes the #to_s
569
- // value for an object the default.
570
533
  RubyObject._proto.toString = function() {
571
534
  return this.$to_s();
572
535
  };
573
536
 
574
- var top_self = Opal.top = new RubyObject._alloc();
537
+ Opal.top = new RubyObject._alloc();
575
538
 
576
539
  var RubyNilClass = define_class(RubyObject, 'NilClass', RubyObject);
577
540
  Opal.nil = new RubyNilClass._alloc();
578
-
579
- bridge_class(Array, T_OBJECT | T_ARRAY, 'Array');
580
- bridge_class(Number, T_OBJECT | T_NUMBER, 'Numeric');
581
-
582
- bridge_class(String, T_OBJECT | T_STRING, 'String');
583
- bridge_class(Boolean, T_OBJECT | T_BOOLEAN, 'Boolean');
584
- bridge_class(Function, T_OBJECT | T_PROC, 'Proc');
585
- bridge_class(RegExp, T_OBJECT, 'Regexp');
586
-
587
- var RubyMatch = define_class(RubyObject, 'MatchData', RubyObject);
588
- var RubyRange = define_class(RubyObject, 'Range', RubyObject);
589
- RubyRange._proto._flags = T_OBJECT | T_RANGE;
590
-
591
- var RubyException = bridge_class(Error, T_OBJECT, 'Exception');
592
- var RubyStandardError = define_class(RubyObject, 'StandardError', RubyException);
593
- var RubyRuntimeError = define_class(RubyObject, 'RuntimeError', RubyException);
594
- var RubyLocalJumpError = define_class(RubyObject, 'LocalJumpError', RubyStandardError);
595
- var RubyTypeError = define_class(RubyObject, 'TypeError', RubyStandardError);
596
- var RubyNameError = define_class(RubyObject, 'NameError', RubyStandardError);
597
- var RubyNoMethodError = define_class(RubyObject, 'NoMethodError', RubyNameError);
598
- var RubyArgError = define_class(RubyObject, 'ArgumentError', RubyStandardError);
599
- var RubyScriptError = define_class(RubyObject, 'ScriptError', RubyException);
600
- var RubyLoadError = define_class(RubyObject, 'LoadError', RubyScriptError);
601
- var RubyIndexError = define_class(RubyObject, 'IndexError', RubyStandardError);
602
- var RubyKeyError = define_class(RubyObject, 'KeyError', RubyIndexError);
603
- var RubyRangeError = define_class(RubyObject, 'RangeError', RubyStandardError);
604
- var RubyNotImplError = define_class(RubyObject, 'NotImplementedError', RubyException);
605
-
606
- RubyException._alloc.prototype.toString = function() {
607
- return this._klass._name + ': ' + this.message;
608
- };
541
+ Opal.nil.call = Opal.nil.apply = no_block_given;
609
542
 
610
543
  var breaker = Opal.breaker = new Error('unexpected break');
611
- breaker._klass = RubyLocalJumpError;
612
544
  breaker.$t = function() { throw this; };
613
-