opal 0.3.18 → 0.3.19

Sign up to get free protection for your applications and to get access to all the features.
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
-