opal 1.2.0.beta1 → 1.2.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/CHANGELOG.md +53 -0
- data/UNRELEASED.md +5 -1
- data/lib/opal/parser/patch.rb +10 -0
- data/lib/opal/rewriter.rb +2 -0
- data/lib/opal/rewriters/pattern_matching.rb +287 -0
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/hash.rb +9 -0
- data/opal/corelib/pattern_matching.rb +159 -0
- data/opal/opal/full.rb +1 -0
- data/spec/filters/bugs/array.rb +0 -1
- data/spec/filters/bugs/hash.rb +1 -6
- data/spec/filters/bugs/language.rb +21 -76
- data/spec/filters/bugs/string.rb +1 -0
- data/spec/filters/bugs/struct.rb +0 -10
- data/spec/filters/unsupported/refinements.rb +3 -0
- data/spec/opal/core/language/pattern_matching_spec.rb +124 -0
- data/stdlib/promise/v1.rb +1 -0
- data/stdlib/promise/v2.rb +386 -0
- data/tasks/releasing.rake +1 -1
- data/tasks/testing.rake +0 -1
- data/test/opal/promisev2/test_always.rb +63 -0
- data/test/opal/promisev2/test_error.rb +16 -0
- data/test/opal/promisev2/test_rescue.rb +59 -0
- data/test/opal/promisev2/test_then.rb +90 -0
- data/test/opal/promisev2/test_trace.rb +52 -0
- data/test/opal/promisev2/test_value.rb +16 -0
- data/test/opal/promisev2/test_when.rb +35 -0
- metadata +24 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f13610ebfa130a3b3379a2d23f3fc077de87e4fd69c33248a87bdf23e144686a
|
4
|
+
data.tar.gz: 275fa37ed3f201f2c716bcf8f05cc5fcd5ff42dec5aaae1b4753c126a629d5c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5a9d1f1494542fd5d1669bb16548b5a335777398a3d84945dbabb8477cedd79f1fd1fc251f663e9f22a518a9a7c3d361f83fb14c860bc3cb36b79c7cd6c40b8
|
7
|
+
data.tar.gz: 90f237673bc19937ee643fbe5562cd348476f975a90348c95138785457a6da342b4df98a48d14b223a938e9c91ac603fde0d2c5cbe18982ec1bcc3c1e6d4c375
|
data/.rubocop.yml
CHANGED
@@ -107,8 +107,9 @@ Layout/SpaceAroundOperators:
|
|
107
107
|
|
108
108
|
Lint/BooleanSymbol:
|
109
109
|
Exclude:
|
110
|
-
# There are AST nodes with types :true and :false
|
110
|
+
# There are AST nodes and rewriters with types :true and :false
|
111
111
|
- 'lib/opal/nodes/**/*.rb'
|
112
|
+
- 'lib/opal/rewriters/**/*.rb'
|
112
113
|
|
113
114
|
Lint/InheritException:
|
114
115
|
Exclude:
|
data/CHANGELOG.md
CHANGED
@@ -15,6 +15,59 @@ Changes are grouped as follows:
|
|
15
15
|
|
16
16
|
|
17
17
|
|
18
|
+
## [1.2.0](https://github.com/opal/opal/compare/v1.1.1...1.2.0) - 2021-07-28
|
19
|
+
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
- Support for multiple arguments in Hash#{merge, merge!, update} ([#2187](https://github.com/opal/opal/pull/2187))
|
24
|
+
- Support for Ruby 3.0 forward arguments: `def a(...) puts(...) end` ([#2153](https://github.com/opal/opal/pull/2153))
|
25
|
+
- Support for beginless and endless ranges: `(1..)`, `(..1)` ([#2150](https://github.com/opal/opal/pull/2150))
|
26
|
+
- Preliminary support for `**nil` argument - see #2240 to note limitations ([#2152](https://github.com/opal/opal/pull/2152))
|
27
|
+
- Support for `Random::Formatters` which add methods `#{hex,base64,urlsafe_base64,uuid,random_float,random_number,alphanumeric}` to `Random` and `SecureRandom` ([#2218](https://github.com/opal/opal/pull/2218))
|
28
|
+
- Basic support for ObjectSpace finalizers and ObjectSpace::WeakMap ([#2247](https://github.com/opal/opal/pull/2247))
|
29
|
+
- A more robust support for encodings (especially binary strings) ([#2235](https://github.com/opal/opal/pull/2235))
|
30
|
+
- Support for `"\x80"` syntax in String literals ([#2235](https://github.com/opal/opal/pull/2235))
|
31
|
+
- Added `String#+@`, `String#-@` ([#2235](https://github.com/opal/opal/pull/2235))
|
32
|
+
- Support for `begin <CODE> end while <CONDITION>` ([#2255](https://github.com/opal/opal/pull/2255))
|
33
|
+
|
34
|
+
### Fixed
|
35
|
+
|
36
|
+
- Encoding lookup was working only with uppercase names, not giving any errors for wrong ones (#2181, #2183, #2190)
|
37
|
+
- Fix `Number#to_i` with huge number ([#2191](https://github.com/opal/opal/pull/2191))
|
38
|
+
- Add regexp support to `String#start_with` ([#2198](https://github.com/opal/opal/pull/2198))
|
39
|
+
- `String#bytes` now works in strict mode ([#2194](https://github.com/opal/opal/pull/2194))
|
40
|
+
- Fix nested module inclusion ([#2053](https://github.com/opal/opal/pull/2053))
|
41
|
+
- SecureRandom is now cryptographically secure on most platforms (#2218, #2170)
|
42
|
+
- Fix performance regression for `Array#unshift` on v8 > 7.1 ([#2116](https://github.com/opal/opal/pull/2116))
|
43
|
+
- String subclasses now call `#initialize` with multiple arguments correctly (with a limitation caused by the String immutability issue, that a source string must be the first argument and `#initialize` can't change its value) (#2238, #2185)
|
44
|
+
- Number#step is moved to Numeric ([#2100](https://github.com/opal/opal/pull/2100))
|
45
|
+
- Fix class Class < superclass for invalid superclasses ([#2123](https://github.com/opal/opal/pull/2123))
|
46
|
+
- Fix `String#unpack("U*")` on binary strings with latin1 high characters, fix performance regression on that call (#2235, #2189, #2129, #2099, #2094, #2000, #2128)
|
47
|
+
- Fix `String#to_json` output on some edge cases ([#2235](https://github.com/opal/opal/pull/2235))
|
48
|
+
- Rework class variables to support inheritance correctly ([#2251](https://github.com/opal/opal/pull/2251))
|
49
|
+
- ISO-8859-1 and US-ASCII encodings are now separated as in MRI ([#2235](https://github.com/opal/opal/pull/2235))
|
50
|
+
- `String#b` no longer modifies object strings in-place ([#2235](https://github.com/opal/opal/pull/2235))
|
51
|
+
|
52
|
+
### Changed
|
53
|
+
|
54
|
+
- `String#unpack`, `Array#pack`, `String#chars`, `String#length`, `Number#chr`, and (only partially) `String#+` are now encoding aware ([#2235](https://github.com/opal/opal/pull/2235))
|
55
|
+
- `String#inspect` now uses `\x` for binary stirngs ([#2235](https://github.com/opal/opal/pull/2235))
|
56
|
+
- `if RUBY_ENGINE == "opal"` and friends are now outputing less JS code (#2159, #1965)
|
57
|
+
- `Array`: `to_a`, `slice`/`[]`, `uniq`, `*`, `difference`/`-`, `intersection`/`&`, `union`/`|`, flatten now return Array, not a subclass, as Ruby 3.0 does ([#2237](https://github.com/opal/opal/pull/2237))
|
58
|
+
- `Array`: `difference`, `intersection`, `union` now accept multiple arguments ([#2237](https://github.com/opal/opal/pull/2237))
|
59
|
+
|
60
|
+
### Deprecated
|
61
|
+
|
62
|
+
- Stopped testing Opal on Ruby 2.5 since it reached EOL.
|
63
|
+
|
64
|
+
### Removed
|
65
|
+
|
66
|
+
- Removed support for the outdated `c_lexer`, it was optional and didn't work for the last few releases of parser ([#2235](https://github.com/opal/opal/pull/2235))
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
18
71
|
## [1.1.1](https://github.com/opal/opal/compare/v1.1.0...v1.1.1) - 2021-02-23
|
19
72
|
|
20
73
|
|
data/UNRELEASED.md
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
### Added
|
2
1
|
|
3
2
|
- Support for multiple arguments in Hash#{merge, merge!, update} (#2187)
|
4
3
|
- Support for Ruby 3.0 forward arguments: `def a(...) puts(...) end` (#2153)
|
@@ -10,6 +9,10 @@
|
|
10
9
|
- Support for `"\x80"` syntax in String literals (#2235)
|
11
10
|
- Added `String#+@`, `String#-@` (#2235)
|
12
11
|
- Support for `begin <CODE> end while <CONDITION>` (#2255)
|
12
|
+
- Added Hash#except and `Hash#except!` (#2243)
|
13
|
+
- Parser 3.0: Implement pattern matching (as part of this `{Array,Hash,Struct}#{deconstruct,deconstruct_keys} methods were added)` (#2243)
|
14
|
+
- [experimental] Reimplement Promise to make it bridged with JS native Promise, this new implementation can be used by requiring `promise/v2` (#2220)
|
15
|
+
|
13
16
|
|
14
17
|
### Fixed
|
15
18
|
|
@@ -28,6 +31,7 @@
|
|
28
31
|
- Rework class variables to support inheritance correctly (#2251)
|
29
32
|
- ISO-8859-1 and US-ASCII encodings are now separated as in MRI (#2235)
|
30
33
|
- `String#b` no longer modifies object strings in-place (#2235)
|
34
|
+
- Parser::Builder::Default.check_lvar_name patch (#2195)
|
31
35
|
|
32
36
|
### Changed
|
33
37
|
|
data/lib/opal/parser/patch.rb
CHANGED
@@ -38,6 +38,16 @@ if RUBY_ENGINE == 'opal'
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
class Parser::Builders::Default
|
43
|
+
def check_lvar_name(name, loc)
|
44
|
+
if name =~ `/^[\p{Ll}|_][\p{L}\p{Nl}\p{Nd}_]*$/u`
|
45
|
+
# OK
|
46
|
+
else
|
47
|
+
diagnostic :error, :lvar_name, { name: name }, loc
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
41
51
|
end
|
42
52
|
|
43
53
|
module AST::Processor::Mixin
|
data/lib/opal/rewriter.rb
CHANGED
@@ -6,6 +6,7 @@ require 'opal/rewriters/explicit_writer_return'
|
|
6
6
|
require 'opal/rewriters/js_reserved_words'
|
7
7
|
require 'opal/rewriters/block_to_iter'
|
8
8
|
require 'opal/rewriters/dot_js_syntax'
|
9
|
+
require 'opal/rewriters/pattern_matching'
|
9
10
|
require 'opal/rewriters/logical_operator_assignment'
|
10
11
|
require 'opal/rewriters/binary_operator_assignment'
|
11
12
|
require 'opal/rewriters/hashes/key_duplicates_rewriter'
|
@@ -49,6 +50,7 @@ module Opal
|
|
49
50
|
use Rewriters::ForwardArgs
|
50
51
|
use Rewriters::BlockToIter
|
51
52
|
use Rewriters::DotJsSyntax
|
53
|
+
use Rewriters::PatternMatching
|
52
54
|
use Rewriters::JsReservedWords
|
53
55
|
use Rewriters::LogicalOperatorAssignment
|
54
56
|
use Rewriters::BinaryOperatorAssignment
|
@@ -0,0 +1,287 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'opal/rewriters/base'
|
4
|
+
|
5
|
+
module Opal
|
6
|
+
module Rewriters
|
7
|
+
class PatternMatching < Base
|
8
|
+
def initialize
|
9
|
+
@depth = 0
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
# a => b
|
14
|
+
def on_match_pattern(node)
|
15
|
+
from, pat = *node
|
16
|
+
|
17
|
+
s(:begin,
|
18
|
+
s(:lvasgn, :"$pmvar", from),
|
19
|
+
s(:if,
|
20
|
+
convert_full_pattern(from, pat),
|
21
|
+
nil,
|
22
|
+
raise_no_matching_pattern_error(:"$pmvar")
|
23
|
+
)
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
# a in b
|
28
|
+
def on_match_pattern_p(node)
|
29
|
+
from, pat = *node
|
30
|
+
|
31
|
+
s(:if,
|
32
|
+
convert_full_pattern(from, pat),
|
33
|
+
s(:true),
|
34
|
+
s(:false)
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
# case a; in b; end
|
39
|
+
def on_case_match(node)
|
40
|
+
@depth += 1
|
41
|
+
|
42
|
+
cmvar = :"$cmvar#{@depth}"
|
43
|
+
|
44
|
+
from, *cases, els = *node
|
45
|
+
|
46
|
+
if els
|
47
|
+
process els
|
48
|
+
else
|
49
|
+
els = raise_no_matching_pattern_error(cmvar)
|
50
|
+
end
|
51
|
+
|
52
|
+
s(:begin,
|
53
|
+
s(:lvasgn, cmvar, from),
|
54
|
+
single_case_match(cmvar, *cases, els)
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# raise NoMatchingPatternError, from
|
61
|
+
def raise_no_matching_pattern_error(from)
|
62
|
+
s(:send, nil, :raise,
|
63
|
+
s(:const, nil, :NoMatchingPatternError),
|
64
|
+
s(:lvar, from)
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
# in b
|
69
|
+
def single_case_match(from, *cases, els)
|
70
|
+
cas = cases.shift
|
71
|
+
pat, if_guard, body = *cas
|
72
|
+
|
73
|
+
pat = convert_full_pattern(from, pat)
|
74
|
+
if if_guard
|
75
|
+
guard, = *if_guard
|
76
|
+
case if_guard.type
|
77
|
+
when :if_guard
|
78
|
+
pat = s(:and, pat, guard)
|
79
|
+
when :unless_guard
|
80
|
+
pat = s(:and, pat, s(:send, guard, :!))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
s(:if,
|
85
|
+
pat,
|
86
|
+
process(body),
|
87
|
+
if !cases.empty?
|
88
|
+
single_case_match(from, *cases, els)
|
89
|
+
elsif els != s(:empty_else)
|
90
|
+
els
|
91
|
+
end
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
def convert_full_pattern(from, pat)
|
96
|
+
if from.class == Symbol
|
97
|
+
from = s(:lvar, from)
|
98
|
+
end
|
99
|
+
|
100
|
+
converter = PatternConverter.new(pat)
|
101
|
+
converter.run!
|
102
|
+
|
103
|
+
# a, b, c = ::PatternMatching.(from, [...])
|
104
|
+
s(:masgn,
|
105
|
+
s(:mlhs,
|
106
|
+
*converter.variables
|
107
|
+
),
|
108
|
+
s(:send,
|
109
|
+
s(:const, s(:cbase), :PatternMatching),
|
110
|
+
:call,
|
111
|
+
from,
|
112
|
+
converter.pattern,
|
113
|
+
)
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
class PatternConverter < ::Opal::Rewriters::Base
|
118
|
+
def initialize(pat)
|
119
|
+
@pat = pat
|
120
|
+
@variables = []
|
121
|
+
end
|
122
|
+
|
123
|
+
def run!
|
124
|
+
@outpat = process(@pat)
|
125
|
+
end
|
126
|
+
|
127
|
+
def pattern
|
128
|
+
@outpat
|
129
|
+
end
|
130
|
+
|
131
|
+
def variables
|
132
|
+
@variables.map { |i| s(:lvasgn, i) }
|
133
|
+
end
|
134
|
+
|
135
|
+
# a
|
136
|
+
def on_match_var(node)
|
137
|
+
var, = *node
|
138
|
+
|
139
|
+
@variables << var
|
140
|
+
|
141
|
+
s(:sym, :var)
|
142
|
+
end
|
143
|
+
|
144
|
+
# [...] => a
|
145
|
+
def on_match_as(node)
|
146
|
+
pat, save = *node
|
147
|
+
|
148
|
+
process(save)
|
149
|
+
array(s(:sym, :save), process(pat))
|
150
|
+
end
|
151
|
+
|
152
|
+
def on_literal(node)
|
153
|
+
array(s(:sym, :lit), node)
|
154
|
+
end
|
155
|
+
|
156
|
+
alias on_int on_literal
|
157
|
+
alias on_float on_literal
|
158
|
+
alias on_complex on_literal
|
159
|
+
alias on_rational on_literal
|
160
|
+
alias on_array on_literal
|
161
|
+
alias on_str on_literal
|
162
|
+
alias on_dstr on_literal
|
163
|
+
alias on_xstr on_literal
|
164
|
+
alias on_sym on_literal
|
165
|
+
alias on_irange on_literal
|
166
|
+
alias on_erange on_literal
|
167
|
+
alias on_const on_literal
|
168
|
+
alias on_regexp on_literal
|
169
|
+
alias on_lambda on_literal
|
170
|
+
alias on_begin on_literal
|
171
|
+
|
172
|
+
# ^a
|
173
|
+
def on_pin(node)
|
174
|
+
on_literal(node.children.first)
|
175
|
+
end
|
176
|
+
|
177
|
+
# *
|
178
|
+
def on_match_rest(node)
|
179
|
+
if node.children.empty?
|
180
|
+
array(s(:sym, :rest))
|
181
|
+
else
|
182
|
+
array(s(:sym, :rest), process(node.children.first))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# {} | []
|
187
|
+
def on_match_alt(node)
|
188
|
+
array(s(:sym, :any), *node.children.map(&method(:process)))
|
189
|
+
end
|
190
|
+
|
191
|
+
# MyStructName
|
192
|
+
def on_const_pattern(node)
|
193
|
+
array(s(:sym, :all), *node.children.map(&method(:process)))
|
194
|
+
end
|
195
|
+
|
196
|
+
# [0, 1, 2] or [*, 0, 1] or [0, 1, *]
|
197
|
+
def on_array_pattern(node, tail = false)
|
198
|
+
children = *node
|
199
|
+
children << s(:match_rest) if tail
|
200
|
+
|
201
|
+
fixed_size = true
|
202
|
+
array_size = 0
|
203
|
+
|
204
|
+
children = children.each do |i|
|
205
|
+
case i.type
|
206
|
+
when :match_rest
|
207
|
+
fixed_size = false
|
208
|
+
else
|
209
|
+
array_size += 1
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
array(
|
214
|
+
s(:sym, :array),
|
215
|
+
to_ast(fixed_size),
|
216
|
+
to_ast(array_size),
|
217
|
+
to_ast(children.map(&method(:process)))
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
# [0, 1, 2,]
|
222
|
+
def on_array_pattern_with_tail(node)
|
223
|
+
on_array_pattern(node, true)
|
224
|
+
end
|
225
|
+
|
226
|
+
# {a:, b:}
|
227
|
+
def on_hash_pattern(node)
|
228
|
+
children = *node
|
229
|
+
|
230
|
+
any_size = children.empty? ? to_ast(false) : to_ast(true)
|
231
|
+
|
232
|
+
children = children.map do |i|
|
233
|
+
case i.type
|
234
|
+
when :pair
|
235
|
+
array(i.children[0], process(i.children[1]))
|
236
|
+
when :match_var
|
237
|
+
array(s(:sym, i.children[0]), process(i))
|
238
|
+
when :match_nil_pattern
|
239
|
+
any_size = to_ast(false)
|
240
|
+
nil
|
241
|
+
when :match_rest
|
242
|
+
# Capturing rest?
|
243
|
+
if i.children.first
|
244
|
+
any_size = process(i.children.first)
|
245
|
+
else
|
246
|
+
any_size = to_ast(true)
|
247
|
+
end
|
248
|
+
nil
|
249
|
+
end
|
250
|
+
end.compact
|
251
|
+
|
252
|
+
array(s(:sym, :hash), any_size, array(*children))
|
253
|
+
end
|
254
|
+
|
255
|
+
# [*, a, b, *]
|
256
|
+
def on_find_pattern(node)
|
257
|
+
children = *node
|
258
|
+
|
259
|
+
children = children.map(&method(:process))
|
260
|
+
|
261
|
+
array(s(:sym, :find), array(*children))
|
262
|
+
end
|
263
|
+
|
264
|
+
private
|
265
|
+
|
266
|
+
def array(*args)
|
267
|
+
to_ast(args)
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_ast(val)
|
271
|
+
case val
|
272
|
+
when Array
|
273
|
+
s(:array, *val)
|
274
|
+
when Integer
|
275
|
+
s(:int, val)
|
276
|
+
when true
|
277
|
+
s(:true)
|
278
|
+
when false
|
279
|
+
s(:false)
|
280
|
+
when nil
|
281
|
+
s(:nil)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
data/lib/opal/version.rb
CHANGED
data/opal/corelib/constants.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
RUBY_PLATFORM = 'opal'
|
2
2
|
RUBY_ENGINE = 'opal'
|
3
3
|
RUBY_VERSION = '3.0.2'
|
4
|
-
RUBY_ENGINE_VERSION = '1.2.0
|
5
|
-
RUBY_RELEASE_DATE = '2021-07-
|
4
|
+
RUBY_ENGINE_VERSION = '1.2.0'
|
5
|
+
RUBY_RELEASE_DATE = '2021-07-28'
|
6
6
|
RUBY_PATCHLEVEL = 0
|
7
7
|
RUBY_REVISION = '0'
|
8
8
|
RUBY_COPYRIGHT = 'opal - Copyright (C) 2013-2021 Adam Beynon and the Opal contributors'
|