opal 1.4.1 → 1.5.0.rc1

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +5 -3
  3. data/.rubocop.yml +1 -0
  4. data/UNRELEASED.md +37 -2
  5. data/benchmark-ips/bm_js_symbols_vs_strings.rb +39 -14
  6. data/docs/releasing.md +10 -2
  7. data/lib/opal/ast/matcher.rb +77 -0
  8. data/lib/opal/cache.rb +1 -1
  9. data/lib/opal/cli_runners/applescript.rb +2 -0
  10. data/lib/opal/compiler.rb +18 -9
  11. data/lib/opal/nodes/call.rb +73 -28
  12. data/lib/opal/nodes/def.rb +31 -27
  13. data/lib/opal/nodes/definitions.rb +2 -0
  14. data/lib/opal/nodes/helpers.rb +4 -23
  15. data/lib/opal/nodes/if.rb +222 -0
  16. data/lib/opal/nodes/iter.rb +41 -37
  17. data/lib/opal/nodes/literal.rb +2 -2
  18. data/lib/opal/nodes/masgn.rb +15 -17
  19. data/lib/opal/nodes/node_with_args/shortcuts.rb +100 -0
  20. data/lib/opal/nodes/node_with_args.rb +1 -0
  21. data/lib/opal/nodes/top.rb +26 -10
  22. data/lib/opal/nodes.rb +0 -1
  23. data/lib/opal/parser/default_config.rb +3 -2
  24. data/lib/opal/repl.rb +1 -1
  25. data/lib/opal/rewriter.rb +13 -6
  26. data/lib/opal/rewriters/base.rb +12 -1
  27. data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +1 -0
  28. data/lib/opal/version.rb +1 -1
  29. data/opal/corelib/array.rb +23 -28
  30. data/opal/corelib/binding.rb +14 -4
  31. data/opal/corelib/constants.rb +3 -3
  32. data/opal/corelib/hash.rb +2 -2
  33. data/opal/corelib/irb.rb +192 -0
  34. data/opal/corelib/math/polyfills.rb +127 -0
  35. data/opal/corelib/math.rb +14 -194
  36. data/opal/corelib/module.rb +23 -25
  37. data/opal/corelib/number.rb +63 -14
  38. data/opal/corelib/regexp.rb +2 -0
  39. data/opal/corelib/runtime.js +56 -20
  40. data/opal/corelib/string.rb +38 -59
  41. data/opal/corelib/time.rb +106 -68
  42. data/opal/opal/full.rb +0 -1
  43. data/opal/opal.rb +4 -1
  44. data/spec/filters/bugs/date.rb +0 -3
  45. data/spec/filters/bugs/datetime.rb +65 -0
  46. data/spec/filters/bugs/float.rb +0 -18
  47. data/spec/filters/bugs/hash.rb +0 -2
  48. data/spec/filters/bugs/language.rb +0 -3
  49. data/spec/filters/bugs/marshal.rb +0 -1
  50. data/spec/filters/bugs/string.rb +0 -30
  51. data/spec/filters/bugs/time.rb +18 -8
  52. data/spec/lib/cli_spec.rb +2 -2
  53. data/spec/lib/compiler_spec.rb +8 -8
  54. data/spec/lib/rewriters/base_spec.rb +1 -1
  55. data/spec/lib/rewriters/binary_operator_assignment_spec.rb +34 -59
  56. data/spec/lib/rewriters/block_to_iter_spec.rb +3 -6
  57. data/spec/lib/rewriters/dot_js_syntax_spec.rb +2 -5
  58. data/spec/lib/rewriters/for_rewriter_spec.rb +0 -1
  59. data/spec/lib/rewriters/forward_args_spec.rb +2 -3
  60. data/spec/lib/rewriters/js_reserved_words_spec.rb +2 -15
  61. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +64 -89
  62. data/spec/lib/rewriters/numblocks_spec.rb +3 -5
  63. data/spec/lib/rewriters/opal_engine_check_spec.rb +2 -14
  64. data/spec/lib/rewriters/rubyspec/filters_rewriter_spec.rb +10 -2
  65. data/spec/opal/compiler/irb_spec.rb +4 -0
  66. data/spec/opal/core/language/super_spec.rb +26 -0
  67. data/spec/opal/core/regexp/assertions_spec.rb +19 -0
  68. data/spec/opal/core/string/to_proc_spec.rb +19 -0
  69. data/spec/ruby_specs +4 -0
  70. data/spec/support/rewriters_helper.rb +43 -23
  71. data/stdlib/date/date_time.rb +71 -0
  72. data/stdlib/date/formatters.rb +28 -0
  73. data/stdlib/date/infinity.rb +73 -0
  74. data/stdlib/date.rb +77 -214
  75. data/stdlib/opal/repl_js.rb +1 -1
  76. data/stdlib/{opal/replutils.rb → opal-replutils.rb} +3 -3
  77. data/stdlib/time.rb +39 -2
  78. data/stdlib/uri.rb +53 -0
  79. data/tasks/performance/asciidoctor_test.rb.erb +3 -1
  80. data/tasks/performance/optimization_status.rb +3 -2
  81. data/tasks/performance.rake +69 -35
  82. data/tasks/testing.rake +1 -0
  83. data/test/opal/test_uri.rb +35 -0
  84. data/yarn.lock +27 -5
  85. metadata +31 -18
  86. data/lib/opal/nodes/csend.rb +0 -24
  87. data/lib/opal/rewriters/explicit_writer_return.rb +0 -59
  88. data/spec/lib/rewriters/explicit_writer_return_spec.rb +0 -186
  89. data/stdlib/nodejs/irb.rb +0 -43
data/opal/corelib/math.rb CHANGED
@@ -36,124 +36,6 @@ module ::Math
36
36
 
37
37
  module_function
38
38
 
39
- def acos(x)
40
- ::Math.checked :acos, ::Math.float!(x)
41
- end
42
-
43
- unless defined?(`Math.acosh`)
44
- %x{
45
- Math.acosh = function(x) {
46
- return Math.log(x + Math.sqrt(x * x - 1));
47
- }
48
- }
49
- end
50
-
51
- def acosh(x)
52
- ::Math.checked :acosh, ::Math.float!(x)
53
- end
54
-
55
- def asin(x)
56
- ::Math.checked :asin, ::Math.float!(x)
57
- end
58
-
59
- unless defined?(`Math.asinh`)
60
- %x{
61
- Math.asinh = function(x) {
62
- return Math.log(x + Math.sqrt(x * x + 1))
63
- }
64
- }
65
- end
66
-
67
- def asinh(x)
68
- ::Math.checked :asinh, ::Math.float!(x)
69
- end
70
-
71
- def atan(x)
72
- ::Math.checked :atan, ::Math.float!(x)
73
- end
74
-
75
- def atan2(y, x)
76
- ::Math.checked :atan2, ::Math.float!(y), ::Math.float!(x)
77
- end
78
-
79
- unless defined?(`Math.atanh`)
80
- %x{
81
- Math.atanh = function(x) {
82
- return 0.5 * Math.log((1 + x) / (1 - x));
83
- }
84
- }
85
- end
86
-
87
- def atanh(x)
88
- ::Math.checked :atanh, ::Math.float!(x)
89
- end
90
-
91
- unless defined?(`Math.cbrt`)
92
- %x{
93
- Math.cbrt = function(x) {
94
- if (x == 0) {
95
- return 0;
96
- }
97
-
98
- if (x < 0) {
99
- return -Math.cbrt(-x);
100
- }
101
-
102
- var r = x,
103
- ex = 0;
104
-
105
- while (r < 0.125) {
106
- r *= 8;
107
- ex--;
108
- }
109
-
110
- while (r > 1.0) {
111
- r *= 0.125;
112
- ex++;
113
- }
114
-
115
- r = (-0.46946116 * r + 1.072302) * r + 0.3812513;
116
-
117
- while (ex < 0) {
118
- r *= 0.5;
119
- ex++;
120
- }
121
-
122
- while (ex > 0) {
123
- r *= 2;
124
- ex--;
125
- }
126
-
127
- r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
128
- r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
129
- r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
130
- r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
131
-
132
- return r;
133
- }
134
- }
135
- end
136
-
137
- def cbrt(x)
138
- ::Math.checked :cbrt, ::Math.float!(x)
139
- end
140
-
141
- def cos(x)
142
- ::Math.checked :cos, ::Math.float!(x)
143
- end
144
-
145
- unless defined?(`Math.cosh`)
146
- %x{
147
- Math.cosh = function(x) {
148
- return (Math.exp(x) + Math.exp(-x)) / 2;
149
- }
150
- }
151
- end
152
-
153
- def cosh(x)
154
- ::Math.checked :cosh, ::Math.float!(x)
155
- end
156
-
157
39
  unless defined?(`Math.erf`)
158
40
  %x{
159
41
  Opal.prop(Math, 'erf', function(x) {
@@ -180,10 +62,6 @@ module ::Math
180
62
  }
181
63
  end
182
64
 
183
- def erf(x)
184
- ::Math.checked :erf, ::Math.float!(x)
185
- end
186
-
187
65
  unless defined?(`Math.erfc`)
188
66
  %x{
189
67
  Opal.prop(Math, 'erfc', function(x) {
@@ -213,12 +91,22 @@ module ::Math
213
91
  }
214
92
  end
215
93
 
216
- def erfc(x)
217
- ::Math.checked :erfc, ::Math.float!(x)
94
+ # Single argument equivalent functions
95
+ %i[
96
+ acos acosh asin asinh atan atanh cbrt
97
+ cos cosh erf erfc exp sin sinh sqrt tanh
98
+ ].each do |method|
99
+ define_method method do |x|
100
+ ::Math.checked method, ::Math.float!(x)
101
+ end
218
102
  end
219
103
 
220
- def exp(x)
221
- ::Math.checked :exp, ::Math.float!(x)
104
+ def atan2(y, x)
105
+ ::Math.checked :atan2, ::Math.float!(y), ::Math.float!(x)
106
+ end
107
+
108
+ def hypot(x, y)
109
+ ::Math.checked :hypot, ::Math.float!(x), ::Math.float!(y)
222
110
  end
223
111
 
224
112
  def frexp(x)
@@ -332,18 +220,6 @@ module ::Math
332
220
  }
333
221
  end
334
222
 
335
- unless defined?(`Math.hypot`)
336
- %x{
337
- Math.hypot = function(x, y) {
338
- return Math.sqrt(x * x + y * y)
339
- }
340
- }
341
- end
342
-
343
- def hypot(x, y)
344
- ::Math.checked :hypot, ::Math.float!(x), ::Math.float!(y)
345
- end
346
-
347
223
  def ldexp(mantissa, exponent)
348
224
  mantissa = Math.float!(mantissa)
349
225
  exponent = Math.integer!(exponent)
@@ -384,14 +260,6 @@ module ::Math
384
260
  end
385
261
  end
386
262
 
387
- unless defined?(`Math.log10`)
388
- %x{
389
- Math.log10 = function(x) {
390
- return Math.log(x) / Math.LN10;
391
- }
392
- }
393
- end
394
-
395
263
  def log10(x)
396
264
  if ::String === x
397
265
  ::Kernel.raise `$type_error(x, #{::Float})`
@@ -400,14 +268,6 @@ module ::Math
400
268
  ::Math.checked :log10, ::Math.float!(x)
401
269
  end
402
270
 
403
- unless defined?(`Math.log2`)
404
- %x{
405
- Math.log2 = function(x) {
406
- return Math.log(x) / Math.LN2;
407
- }
408
- }
409
- end
410
-
411
271
  def log2(x)
412
272
  if ::String === x
413
273
  ::Kernel.raise `$type_error(x, #{::Float})`
@@ -416,26 +276,6 @@ module ::Math
416
276
  ::Math.checked :log2, ::Math.float!(x)
417
277
  end
418
278
 
419
- def sin(x)
420
- ::Math.checked :sin, ::Math.float!(x)
421
- end
422
-
423
- unless defined?(`Math.sinh`)
424
- %x{
425
- Math.sinh = function(x) {
426
- return (Math.exp(x) - Math.exp(-x)) / 2;
427
- }
428
- }
429
- end
430
-
431
- def sinh(x)
432
- ::Math.checked :sinh, ::Math.float!(x)
433
- end
434
-
435
- def sqrt(x)
436
- ::Math.checked :sqrt, ::Math.float!(x)
437
- end
438
-
439
279
  def tan(x)
440
280
  x = ::Math.float!(x)
441
281
 
@@ -445,24 +285,4 @@ module ::Math
445
285
 
446
286
  ::Math.checked :tan, ::Math.float!(x)
447
287
  end
448
-
449
- unless defined?(`Math.tanh`)
450
- %x{
451
- Math.tanh = function(x) {
452
- if (x == Infinity) {
453
- return 1;
454
- }
455
- else if (x == -Infinity) {
456
- return -1;
457
- }
458
- else {
459
- return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
460
- }
461
- }
462
- }
463
- end
464
-
465
- def tanh(x)
466
- ::Math.checked :tanh, ::Math.float!(x)
467
- end
468
288
  end
@@ -1,4 +1,4 @@
1
- # helpers: truthy, coerce_to, const_set, Object
1
+ # helpers: truthy, coerce_to, const_set, Object, return_ivar, assign_ivar, ivar
2
2
 
3
3
  class ::Module
4
4
  def self.allocate
@@ -131,20 +131,9 @@ class ::Module
131
131
  for (var i = names.length - 1; i >= 0; i--) {
132
132
  var name = names[i],
133
133
  id = '$' + name,
134
- ivar = Opal.ivar(name);
135
-
136
- // the closure here is needed because name will change at the next
137
- // cycle, I wish we could use let.
138
- var body = (function(ivar) {
139
- return function() {
140
- if (this[ivar] == null) {
141
- return nil;
142
- }
143
- else {
144
- return this[ivar];
145
- }
146
- };
147
- })(ivar);
134
+ ivar = $ivar(name);
135
+
136
+ var body = $return_ivar(ivar);
148
137
 
149
138
  // initialize the instance variable as nil
150
139
  Opal.prop(proto, ivar, nil);
@@ -166,15 +155,9 @@ class ::Module
166
155
  for (var i = names.length - 1; i >= 0; i--) {
167
156
  var name = names[i],
168
157
  id = '$' + name + '=',
169
- ivar = Opal.ivar(name);
158
+ ivar = $ivar(name);
170
159
 
171
- // the closure here is needed because name will change at the next
172
- // cycle, I wish we could use let.
173
- var body = (function(ivar){
174
- return function(value) {
175
- return this[ivar] = value;
176
- }
177
- })(ivar);
160
+ var body = $assign_ivar(ivar)
178
161
 
179
162
  body.$$parameters = [['req']];
180
163
  body.$$arity = 1;
@@ -396,14 +379,29 @@ class ::Module
396
379
  end
397
380
 
398
381
  %x{
399
- var id = '$' + name;
382
+ if (typeof(Proxy) !== 'undefined') {
383
+ var meta = Object.create(null)
384
+
385
+ block.$$proxy_target = block
386
+ block = new Proxy(block, {
387
+ apply: function(target, self, args) {
388
+ var old_name = target.$$jsid
389
+ target.$$jsid = name;
390
+ try {
391
+ return target.apply(self, args);
392
+ } finally {
393
+ target.$$jsid = old_name
394
+ }
395
+ }
396
+ })
397
+ }
400
398
 
401
399
  block.$$jsid = name;
402
400
  block.$$s = null;
403
401
  block.$$def = block;
404
402
  block.$$define_meth = true;
405
403
 
406
- return Opal.defn(self, id, block);
404
+ return Opal.defn(self, '$' + name, block);
407
405
  }
408
406
  end
409
407
 
@@ -263,20 +263,6 @@ class ::Number < ::Numeric
263
263
  end
264
264
  end
265
265
 
266
- def ===(other)
267
- %x{
268
- if (other.$$is_number) {
269
- return self.valueOf() === other.valueOf();
270
- }
271
- else if (#{other.respond_to? :==}) {
272
- return #{other == self};
273
- }
274
- else {
275
- return false;
276
- }
277
- }
278
- end
279
-
280
266
  def ==(other)
281
267
  %x{
282
268
  if (other.$$is_number) {
@@ -291,6 +277,8 @@ class ::Number < ::Numeric
291
277
  }
292
278
  end
293
279
 
280
+ alias === ==
281
+
294
282
  def abs
295
283
  `Math.abs(self)`
296
284
  end
@@ -817,6 +805,67 @@ class ::Number < ::Numeric
817
805
  `self == -Infinity || 1 / self < 0`
818
806
  end
819
807
 
808
+ %x{
809
+ function numberToUint8Array(num) {
810
+ var uint8array = new Uint8Array(8);
811
+ new DataView(uint8array.buffer).setFloat64(0, num, true);
812
+ return uint8array;
813
+ }
814
+
815
+ function uint8ArrayToNumber(arr) {
816
+ return new DataView(arr.buffer).getFloat64(0, true);
817
+ }
818
+
819
+ function incrementNumberBit(num) {
820
+ var arr = numberToUint8Array(num);
821
+ for (var i = 0; i < arr.length; i++) {
822
+ if (arr[i] === 0xff) {
823
+ arr[i] = 0;
824
+ } else {
825
+ arr[i]++;
826
+ break;
827
+ }
828
+ }
829
+ return uint8ArrayToNumber(arr);
830
+ }
831
+
832
+ function decrementNumberBit(num) {
833
+ var arr = numberToUint8Array(num);
834
+ for (var i = 0; i < arr.length; i++) {
835
+ if (arr[i] === 0) {
836
+ arr[i] = 0xff;
837
+ } else {
838
+ arr[i]--;
839
+ break;
840
+ }
841
+ }
842
+ return uint8ArrayToNumber(arr);
843
+ }
844
+ }
845
+
846
+ def next_float
847
+ return ::Float::INFINITY if self == ::Float::INFINITY
848
+ return ::Float::NAN if nan?
849
+
850
+ if self >= 0
851
+ # Math.abs() is needed to handle -0.0
852
+ `incrementNumberBit(Math.abs(self))`
853
+ else
854
+ `decrementNumberBit(self)`
855
+ end
856
+ end
857
+
858
+ def prev_float
859
+ return -::Float::INFINITY if self == -::Float::INFINITY
860
+ return ::Float::NAN if nan?
861
+
862
+ if self > 0
863
+ `decrementNumberBit(self)`
864
+ else
865
+ `-incrementNumberBit(Math.abs(self))`
866
+ end
867
+ end
868
+
820
869
  alias arg angle
821
870
  alias eql? ==
822
871
  alias fdiv /
@@ -83,6 +83,8 @@ class ::Regexp < `RegExp`
83
83
  #{::Kernel.raise ::RegexpError, "too short escape sequence: /#{regexp}/"}
84
84
  }
85
85
 
86
+ regexp = regexp.replace('\\A', '^').replace('\\z', '$')
87
+
86
88
  if (options === undefined || #{!options}) {
87
89
  return new RegExp(regexp);
88
90
  }
@@ -184,7 +184,22 @@
184
184
  };
185
185
 
186
186
  Opal.coerce_to = function(object, type, method, args) {
187
- if (type['$==='](object)) return object;
187
+ var body;
188
+
189
+ if (method === 'to_int' && type === Opal.Integer && object.$$is_number)
190
+ return object < 0 ? Math.ceil(object) : Math.floor(object);
191
+
192
+ if (method === 'to_str' && type === Opal.String && object.$$is_string)
193
+ return object;
194
+
195
+ if (Opal.is_a(object, type)) return object;
196
+
197
+ // Fast path for the most common situation
198
+ if (object['$respond_to?'].$$pristine && object.$method_missing.$$pristine) {
199
+ body = object['$' + method];
200
+ if (body == null || body.$$stub) throw Opal.type_error(object, type);
201
+ return body.apply(object, args);
202
+ }
188
203
 
189
204
  if (!object['$respond_to?'](method)) {
190
205
  throw Opal.type_error(object, type);
@@ -1592,7 +1607,10 @@
1592
1607
  }
1593
1608
 
1594
1609
  if (implicit && current_func.$$define_meth) {
1595
- throw Opal.RuntimeError.$new("implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly");
1610
+ throw Opal.RuntimeError.$new(
1611
+ "implicit argument passing of super from method defined by define_method() is not supported. " +
1612
+ "Specify all arguments explicitly"
1613
+ );
1596
1614
  }
1597
1615
 
1598
1616
  if (current_func.$$def) {
@@ -1708,15 +1726,9 @@
1708
1726
  return (klass.$$is_integer_class) ? (object % 1) === 0 : true;
1709
1727
  }
1710
1728
 
1711
- var i, length, ancestors = Opal.ancestors(object.$$is_class ? Opal.get_singleton_class(object) : (object.$$meta || object.$$class));
1729
+ var ancestors = Opal.ancestors(object.$$is_class ? Opal.get_singleton_class(object) : (object.$$meta || object.$$class));
1712
1730
 
1713
- for (i = 0, length = ancestors.length; i < length; i++) {
1714
- if (ancestors[i] === klass) {
1715
- return true;
1716
- }
1717
- }
1718
-
1719
- return false;
1731
+ return ancestors.indexOf(klass) !== -1;
1720
1732
  };
1721
1733
 
1722
1734
  // Helpers for extracting kwsplats
@@ -1874,8 +1886,6 @@
1874
1886
  Opal.send = function(recv, method, args, block, blockopts) {
1875
1887
  var body;
1876
1888
 
1877
- apply_blockopts(block, blockopts);
1878
-
1879
1889
  if (typeof(method) === 'function') {
1880
1890
  body = method;
1881
1891
  method = null;
@@ -1885,7 +1895,7 @@
1885
1895
  throw Opal.NameError.$new("Passed method should be a string or a function");
1886
1896
  }
1887
1897
 
1888
- return Opal.send2(recv, body, method, args, block);
1898
+ return Opal.send2(recv, body, method, args, block, blockopts);
1889
1899
  };
1890
1900
 
1891
1901
  Opal.send2 = function(recv, body, method, args, block, blockopts) {
@@ -1909,8 +1919,6 @@
1909
1919
  ancestors = Opal.ancestors(recv.$$class);
1910
1920
  }
1911
1921
 
1912
- apply_blockopts(block, blockopts);
1913
-
1914
1922
  // For all ancestors that there are, starting from the closest to the furthest...
1915
1923
  for (i = 0; i < ancestors.length; i++) {
1916
1924
  ancestor = Opal.id(ancestors[i]);
@@ -1930,14 +1938,14 @@
1930
1938
  // Does this module define a method we want to call?
1931
1939
  if (typeof refine_module.$$prototype['$'+method] !== 'undefined') {
1932
1940
  body = refine_module.$$prototype['$'+method];
1933
- return Opal.send2(recv, body, method, args, block);
1941
+ return Opal.send2(recv, body, method, args, block, blockopts);
1934
1942
  }
1935
1943
  }
1936
1944
  }
1937
1945
  }
1938
1946
  }
1939
1947
 
1940
- return Opal.send(recv, method, args, block);
1948
+ return Opal.send(recv, method, args, block, blockopts);
1941
1949
  };
1942
1950
 
1943
1951
  Opal.lambda = function(block, blockopts) {
@@ -2654,7 +2662,7 @@
2654
2662
  if (typeof Promise !== 'undefined' && retval instanceof Promise) {
2655
2663
  // A special case of require having an async top:
2656
2664
  // We will need to await it.
2657
- return retval.then(function() { return true; });
2665
+ return retval.then($return_val(true));
2658
2666
  }
2659
2667
  }
2660
2668
  else {
@@ -2777,13 +2785,15 @@
2777
2785
  Opal.rb_ge = function(l,r) { return (typeof(l) === 'number' && typeof(r) === 'number') ? l >= r : l['$>='](r); }
2778
2786
 
2779
2787
  // Optimized helpers for calls like $truthy((a)['$==='](b)) -> $eqeqeq(a, b)
2780
- Opal.eqeq = function(lhs, rhs) {
2788
+ function $eqeq(lhs, rhs) {
2781
2789
  if ((typeof lhs === 'number' && typeof rhs === 'number') ||
2782
2790
  (typeof lhs === 'string' && typeof rhs === 'string')) {
2783
2791
  return lhs === rhs;
2784
2792
  }
2785
2793
  return $truthy((lhs)['$=='](rhs));
2786
2794
  };
2795
+ Opal.eqeq = $eqeq;
2796
+
2787
2797
  Opal.eqeqeq = function(lhs, rhs) {
2788
2798
  if ((typeof lhs === 'number' && typeof rhs === 'number') ||
2789
2799
  (typeof lhs === 'string' && typeof rhs === 'string')) {
@@ -2804,7 +2814,33 @@
2804
2814
  return $truthy(arg['$!']());
2805
2815
  }
2806
2816
 
2817
+ // Shortcuts - optimized function generators for simple kinds of functions
2818
+ function $return_val(arg) {
2819
+ return function() {
2820
+ return arg;
2821
+ }
2822
+ }
2823
+ Opal.return_val = $return_val;
2807
2824
 
2825
+ Opal.return_self = function() {
2826
+ return this;
2827
+ }
2828
+ Opal.return_ivar = function(ivar) {
2829
+ return function() {
2830
+ if (this[ivar] == null) this[ivar] = nil;
2831
+ return this[ivar];
2832
+ }
2833
+ }
2834
+ Opal.assign_ivar = function(ivar) {
2835
+ return function(val) {
2836
+ return this[ivar] = val;
2837
+ }
2838
+ }
2839
+ Opal.assign_ivar_val = function(ivar, static_val) {
2840
+ return function() {
2841
+ return this[ivar] = static_val;
2842
+ }
2843
+ }
2808
2844
 
2809
2845
  // Initialization
2810
2846
  // --------------
@@ -2856,7 +2892,7 @@
2856
2892
 
2857
2893
  // Instantiate the main object
2858
2894
  Opal.top = new _Object();
2859
- Opal.top.$to_s = Opal.top.$inspect = function() { return 'main' };
2895
+ Opal.top.$to_s = Opal.top.$inspect = $return_val('main');
2860
2896
  Opal.top.$define_method = top_define_method;
2861
2897
 
2862
2898
  // Foward calls to define_method on the top object to Object