opal 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +1 -1
  4. data/Rakefile +11 -8
  5. data/lib/opal.rb +1 -1
  6. data/lib/opal/version.rb +1 -1
  7. data/opal.gemspec +1 -1
  8. data/{corelib → opal/core}/array.rb +47 -40
  9. data/{corelib → opal/core}/basic_object.rb +4 -0
  10. data/{corelib → opal/core}/boolean.rb +2 -6
  11. data/{corelib → opal/core}/class.rb +0 -0
  12. data/{corelib → opal/core}/comparable.rb +0 -0
  13. data/{corelib → opal/core}/encoding.rb +0 -0
  14. data/{corelib → opal/core}/enumerable.rb +160 -38
  15. data/opal/core/enumerator.rb +416 -0
  16. data/{corelib → opal/core}/error.rb +0 -0
  17. data/{corelib → opal/core}/hash.rb +38 -48
  18. data/{corelib → opal/core}/io.rb +13 -9
  19. data/{corelib → opal/core}/kernel.rb +75 -49
  20. data/{corelib → opal/core}/main.rb +0 -0
  21. data/{corelib → opal/core}/match_data.rb +0 -4
  22. data/{corelib → opal/core}/method.rb +0 -0
  23. data/{corelib → opal/core}/module.rb +24 -3
  24. data/{corelib → opal/core}/nil_class.rb +0 -4
  25. data/{corelib → opal/core}/numeric.rb +3 -4
  26. data/{corelib → opal/core}/proc.rb +0 -4
  27. data/{corelib → opal/core}/range.rb +0 -0
  28. data/{corelib → opal/core}/regexp.rb +0 -4
  29. data/{corelib → opal/core}/runtime.js +0 -0
  30. data/{corelib → opal/core}/string.rb +4 -6
  31. data/{corelib → opal/core}/struct.rb +3 -21
  32. data/{corelib → opal/core}/time.rb +0 -4
  33. data/opal/opal.rb +121 -0
  34. data/spec/corelib/array/select_spec.rb +14 -0
  35. data/spec/filters/20.rb +4 -0
  36. data/spec/filters/bugs/enumerable.rb +1 -48
  37. data/spec/filters/unsupported/enumerator.rb +13 -0
  38. data/spec/opal/compiler/irb_spec.rb +1 -0
  39. data/spec/rubyspecs +1 -0
  40. data/spec/{corelib → stdlib}/native/alias_native_spec.rb +6 -4
  41. data/spec/{corelib → stdlib}/native/each_spec.rb +3 -1
  42. data/spec/{corelib → stdlib}/native/element_reference_spec.rb +3 -1
  43. data/spec/stdlib/native/ext_spec.rb +19 -0
  44. data/spec/{corelib → stdlib}/native/initialize_spec.rb +4 -4
  45. data/spec/{corelib → stdlib}/native/method_missing_spec.rb +13 -1
  46. data/spec/{corelib → stdlib}/native/new_spec.rb +3 -1
  47. data/stdlib/enumerator.rb +1 -0
  48. data/stdlib/json.rb +1 -1
  49. data/stdlib/native.rb +483 -0
  50. metadata +52 -47
  51. data/corelib/enumerator.rb +0 -55
  52. data/corelib/native.rb +0 -270
  53. data/corelib/opal.rb +0 -88
  54. data/spec/corelib/native/ext_spec.rb +0 -5
  55. data/spec/filters/bugs/enumerator.rb +0 -6
@@ -0,0 +1,416 @@
1
+ class Enumerator
2
+ include Enumerable
3
+
4
+ def self.for(object, method = :each, *args, &block)
5
+ %x{
6
+ var obj = #{allocate};
7
+
8
+ obj.object = object;
9
+ obj.size = block;
10
+ obj.method = method;
11
+ obj.args = args;
12
+
13
+ return obj;
14
+ }
15
+
16
+ end
17
+
18
+ def initialize(*, &block)
19
+ if block
20
+ @object = Generator.new(&block)
21
+ @method = :each
22
+ @args = []
23
+ @size = `arguments[0] || nil`
24
+
25
+ if @size
26
+ @size = Opal.coerce_to @size, Integer, :to_int
27
+ end
28
+ else
29
+ @object = `arguments[0]`
30
+ @method = `arguments[1] || "each"`
31
+ @args = `$slice.call(arguments, 2)`
32
+ @size = nil
33
+ end
34
+ end
35
+
36
+ def each(&block)
37
+ return self unless block
38
+
39
+ @object.__send__(@method, *@args, &block)
40
+ end
41
+
42
+ def size
43
+ Proc === @size ? @size.call(*@args) : @size
44
+ end
45
+
46
+ def with_index(offset = 0, &block)
47
+ if offset
48
+ offset = Opal.coerce_to offset, Integer, :to_int
49
+ else
50
+ offset = 0
51
+ end
52
+
53
+ return enum_for :with_index, offset unless block
54
+
55
+ %x{
56
+ var result
57
+
58
+ self.$each._p = function() {
59
+ var param = #{Opal.destructure(`arguments`)},
60
+ value = block(param, index);
61
+
62
+ if (value === $breaker) {
63
+ result = $breaker.$v;
64
+ return $breaker;
65
+ }
66
+
67
+ index++;
68
+ }
69
+
70
+ self.$each();
71
+
72
+ if (result !== undefined) {
73
+ return result;
74
+ }
75
+ }
76
+ end
77
+
78
+ alias with_object each_with_object
79
+
80
+ def inspect
81
+ result = "#<#{self.class.name}: #{@object.inspect}:#{@method}"
82
+
83
+ unless @args.empty?
84
+ result += "(#{@args.inspect[Range.new(1, -2)]})"
85
+ end
86
+
87
+ result + ">"
88
+ end
89
+
90
+ class Generator
91
+ include Enumerable
92
+
93
+ def initialize(&block)
94
+ raise LocalJumpError, 'no block given' unless block
95
+
96
+ @block = block
97
+ end
98
+
99
+ def each(*args, &block)
100
+ yielder = Yielder.new(&block)
101
+
102
+ %x{
103
+ try {
104
+ args.unshift(#{yielder});
105
+
106
+ if ($opal.$yieldX(#@block, args) === $breaker) {
107
+ return $breaker.$v;
108
+ }
109
+ }
110
+ catch (e) {
111
+ if (e === $breaker) {
112
+ return $breaker.$v;
113
+ }
114
+ else {
115
+ throw e;
116
+ }
117
+ }
118
+ }
119
+
120
+ self
121
+ end
122
+ end
123
+
124
+ class Yielder
125
+ def initialize(&block)
126
+ @block = block
127
+ end
128
+
129
+ def yield(*values)
130
+ %x{
131
+ var value = $opal.$yieldX(#@block, values);
132
+
133
+ if (value === $breaker) {
134
+ throw $breaker;
135
+ }
136
+
137
+ return value;
138
+ }
139
+ end
140
+
141
+ def <<(*values)
142
+ self.yield(*values)
143
+
144
+ self
145
+ end
146
+ end
147
+
148
+ class Lazy < self
149
+ class StopLazyError < Exception; end
150
+
151
+ def initialize(object, size = nil, &block)
152
+ unless block_given?
153
+ raise ArgumentError, 'tried to call lazy new without a block'
154
+ end
155
+
156
+ @enumerator = object
157
+
158
+ super size do |yielder, *each_args|
159
+ begin
160
+ object.each(*each_args) {|*args|
161
+ %x{
162
+ args.unshift(#{yielder});
163
+
164
+ if ($opal.$yieldX(block, args) === $breaker) {
165
+ return $breaker;
166
+ }
167
+ }
168
+ }
169
+ rescue Exception
170
+ nil
171
+ end
172
+ end
173
+ end
174
+
175
+ alias force to_a
176
+
177
+ def lazy
178
+ self
179
+ end
180
+
181
+ def collect(&block)
182
+ unless block
183
+ raise ArgumentError, 'tried to call lazy map without a block'
184
+ end
185
+
186
+ Lazy.new(self, enumerator_size) {|enum, *args|
187
+ %x{
188
+ var value = $opal.$yieldX(block, args);
189
+
190
+ if (value === $breaker) {
191
+ return $breaker;
192
+ }
193
+
194
+ #{enum.yield `value`};
195
+ }
196
+ }
197
+ end
198
+
199
+ def collect_concat(&block)
200
+ unless block
201
+ raise ArgumentError, 'tried to call lazy map without a block'
202
+ end
203
+
204
+ Lazy.new(self, nil) {|enum, *args|
205
+ %x{
206
+ var value = $opal.$yieldX(block, args);
207
+
208
+ if (value === $breaker) {
209
+ return $breaker;
210
+ }
211
+
212
+ if (#{`value`.respond_to? :force} && #{`value`.respond_to? :each}) {
213
+ #{`value`.each { |v| enum.yield v }}
214
+ }
215
+ else {
216
+ var array = #{Opal.try_convert `value`, Array, :to_ary};
217
+
218
+ if (array === nil) {
219
+ #{enum.yield `value`};
220
+ }
221
+ else {
222
+ #{`value`.each { |v| enum.yield v }};
223
+ }
224
+ }
225
+ }
226
+ }
227
+ end
228
+
229
+ def drop(n)
230
+ n = Opal.coerce_to n, Integer, :to_int
231
+
232
+ if n < 0
233
+ raise ArgumentError, "attempt to drop negative size"
234
+ end
235
+
236
+ current_size = enumerator_size
237
+ set_size = if Integer === current_size
238
+ n < current_size ? n : current_size
239
+ else
240
+ current_size
241
+ end
242
+
243
+ dropped = 0
244
+ Lazy.new(self, set_size) {|enum, *args|
245
+ if dropped < n
246
+ dropped += 1
247
+ else
248
+ enum.yield(*args)
249
+ end
250
+ }
251
+ end
252
+
253
+ def drop_while(&block)
254
+ unless block
255
+ raise ArgumentError, 'tried to call lazy drop_while without a block'
256
+ end
257
+
258
+ succeeding = true
259
+ Lazy.new(self, nil) {|enum, *args|
260
+ if succeeding
261
+ %x{
262
+ var value = $opal.$yieldX(block, args);
263
+
264
+ if (value === $breaker) {
265
+ return $breaker;
266
+ }
267
+
268
+ if (#{Opal.falsy?(`value`)}) {
269
+ succeeding = false;
270
+
271
+ #{enum.yield(*args)};
272
+ }
273
+ }
274
+ else
275
+ enum.yield(*args)
276
+ end
277
+ }
278
+ end
279
+
280
+ def enum_for(method = :each, *args, &block)
281
+ self.class.for(self, method, *args, &block)
282
+ end
283
+
284
+ def find_all(&block)
285
+ unless block
286
+ raise ArgumentError, 'tried to call lazy select without a block'
287
+ end
288
+
289
+ Lazy.new(self, nil) {|enum, *args|
290
+ %x{
291
+ var value = $opal.$yieldX(block, args);
292
+
293
+ if (value === $breaker) {
294
+ return $breaker;
295
+ }
296
+
297
+ if (#{Opal.truthy?(`value`)}) {
298
+ #{enum.yield(*args)};
299
+ }
300
+ }
301
+ }
302
+ end
303
+
304
+ alias flat_map collect_concat
305
+
306
+ def grep(pattern, &block)
307
+ if block
308
+ Lazy.new(self, nil) {|enum, *args|
309
+ %x{
310
+ var param = #{Opal.destructure(args)},
311
+ value = #{pattern === `param`};
312
+
313
+ if (#{Opal.truthy?(`value`)}) {
314
+ value = $opal.$yield1(block, param);
315
+
316
+ if (value === $breaker) {
317
+ return $breaker;
318
+ }
319
+
320
+ #{enum.yield `$opal.$yield1(block, param)`};
321
+ }
322
+ }
323
+ }
324
+ else
325
+ Lazy.new(self, nil) {|enum, *args|
326
+ %x{
327
+ var param = #{Opal.destructure(args)},
328
+ value = #{pattern === `param`};
329
+
330
+ if (#{Opal.truthy?(`value`)}) {
331
+ #{enum.yield `param`};
332
+ }
333
+ }
334
+ }
335
+ end
336
+ end
337
+
338
+ alias map collect
339
+
340
+ alias select find_all
341
+
342
+ def reject(&block)
343
+ unless block
344
+ raise ArgumentError, 'tried to call lazy reject without a block'
345
+ end
346
+
347
+ Lazy.new(self, nil) {|enum, *args|
348
+ %x{
349
+ var value = $opal.$yieldX(block, args);
350
+
351
+ if (value === $breaker) {
352
+ return $breaker;
353
+ }
354
+
355
+ if (#{Opal.falsy?(`value`)}) {
356
+ #{enum.yield(*args)};
357
+ }
358
+ }
359
+ }
360
+ end
361
+
362
+ def take(n)
363
+ n = Opal.coerce_to n, Integer, :to_int
364
+
365
+ if n < 0
366
+ raise ArgumentError, "attempt to take negative size"
367
+ end
368
+
369
+ current_size = enumerator_size
370
+ set_size = if Integer === current_size
371
+ n < current_size ? n : current_size
372
+ else
373
+ current_size
374
+ end
375
+
376
+ taken = 0
377
+ Lazy.new(self, set_size) {|enum, *args|
378
+ if taken < n
379
+ enum.yield(*args)
380
+ taken += 1
381
+ else
382
+ raise StopLazyError
383
+ end
384
+ }
385
+ end
386
+
387
+ def take_while(&block)
388
+ unless block
389
+ raise ArgumentError, 'tried to call lazy take_while without a block'
390
+ end
391
+
392
+ Lazy.new(self, nil) {|enum, *args|
393
+ %x{
394
+ var value = $opal.$yieldX(block, args);
395
+
396
+ if (value === $breaker) {
397
+ return $breaker;
398
+ }
399
+
400
+ if (#{Opal.truthy?(`value`)}) {
401
+ #{enum.yield(*args)};
402
+ }
403
+ else {
404
+ #{raise StopLazyError};
405
+ }
406
+ }
407
+ }
408
+ end
409
+
410
+ alias to_enum enum_for
411
+
412
+ def inspect
413
+ "#<#{self.class.name}: #{@enumerator.inspect}>"
414
+ end
415
+ end
416
+ end
File without changes
@@ -28,8 +28,9 @@ class Hash
28
28
  }
29
29
  }
30
30
  else {
31
- for (var i = 0, length = arguments.length, key; i < length; i++) {
32
- var key = arguments[i], obj = arguments[++i];
31
+ for (var i = 0, length = arguments.length; i < length; i++) {
32
+ var key = arguments[i],
33
+ obj = arguments[++i];
33
34
 
34
35
  if (assocs[key] == null) {
35
36
  keys.push(key);
@@ -50,8 +51,10 @@ class Hash
50
51
  %x{
51
52
  var $hash2 = Opal.hash2 = function(keys, map) {
52
53
  var hash = new Hash._alloc;
54
+
53
55
  hash.keys = keys;
54
- hash.map = map;
56
+ hash.map = map;
57
+
55
58
  return hash;
56
59
  };
57
60
  }
@@ -65,8 +68,10 @@ class Hash
65
68
  def self.allocate
66
69
  %x{
67
70
  var hash = new self._alloc;
68
- hash.map = {};
71
+
72
+ hash.map = {};
69
73
  hash.keys = [];
74
+
70
75
  return hash;
71
76
  }
72
77
  end
@@ -74,20 +79,10 @@ class Hash
74
79
  def initialize(defaults = undefined, &block)
75
80
  %x{
76
81
  if (defaults != null) {
77
- if (defaults.constructor == Object) {
78
- var map = self.map, keys = self.keys;
79
-
80
- for (var key in defaults) {
81
- keys.push(key);
82
- map[key] = defaults[key];
83
- }
84
- }
85
- else {
86
- self.none = defaults;
87
- }
82
+ self.none = defaults;
88
83
  }
89
84
  else if (block !== nil) {
90
- self.proc = block;
85
+ self.proc = block;
91
86
  }
92
87
 
93
88
  return self;
@@ -181,20 +176,25 @@ class Hash
181
176
 
182
177
  def clone
183
178
  %x{
184
- var result = new self._klass._alloc();
185
-
186
- result.map = {}; result.keys = [];
187
-
188
- var map = self.map,
189
- map2 = result.map,
190
- keys2 = result.keys;
179
+ var map = {},
180
+ keys = [];
191
181
 
192
182
  for (var i = 0, length = self.keys.length; i < length; i++) {
193
- keys2.push(self.keys[i]);
194
- map2[self.keys[i]] = map[self.keys[i]];
183
+ var key = self.keys[i],
184
+ value = self.map[key];
185
+
186
+ keys.push(key);
187
+ map[key] = value;
195
188
  }
196
189
 
197
- return result;
190
+ var hash = new self._klass._alloc();
191
+
192
+ hash.map = map;
193
+ hash.keys = keys;
194
+ hash.none = self.none;
195
+ hash.proc = self.proc;
196
+
197
+ return hash;
198
198
  }
199
199
  end
200
200
 
@@ -720,34 +720,24 @@ class Hash
720
720
  }
721
721
  end
722
722
 
723
- def to_hash
724
- self
725
- end
726
-
727
- def to_n
723
+ def to_h
728
724
  %x{
729
- var result = {},
730
- keys = self.keys,
731
- map = self.map,
732
- bucket,
733
- value;
734
-
735
- for (var i = 0, length = keys.length; i < length; i++) {
736
- var key = keys[i],
737
- obj = map[key];
725
+ var hash = new Hash._alloc,
726
+ cloned = #{clone};
738
727
 
739
- if (#{`obj`.respond_to? :to_n}) {
740
- result[key] = #{`obj`.to_n};
741
- }
742
- else {
743
- result[key] = obj;
744
- }
745
- }
728
+ hash.map = cloned.map;
729
+ hash.keys = cloned.keys;
730
+ hash.none = cloned.none;
731
+ hash.proc = cloned.proc;
746
732
 
747
- return result;
733
+ return hash;
748
734
  }
749
735
  end
750
736
 
737
+ def to_hash
738
+ self
739
+ end
740
+
751
741
  alias to_s inspect
752
742
 
753
743
  alias update merge!