git.s-ol.nu alive / a34fbc4
base.match: predicate fn matching s-ol 6 months ago
2 changed file(s) with 172 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
8787
8888 --- Base Result Pattern.
8989 --
90 -- When instantiated with `type`, only succeeds for `Result`s whose value and
91 -- meta types match.
90 -- When instantiated with `type`, only succeeds for `Result`s whose type and
91 -- metatypes match.
9292 --
9393 -- Otherwise, matches Streams based only on `metatype` for the first match, but
9494 -- using both afterwards (recall mode).
9595 --
9696 -- @function Type
97 -- @tparam string metatype `'~', '!' or '='
97 -- @tparam ?string metatype `'~', '!' or '='
9898 -- @tparam ?string type type name
9999 class Type extends Pattern
100100 new: (@metatype, @type, @recall=false) =>
101101
102102 casts = { '!!': true, '==': true, '~~': true, '~=': true }
103103 capture: (seq, i) =>
104 return unless seq[i]
105 type, mt = seq[i]\type!, seq[i]\metatype!
104 elem = seq[i]
105 return unless elem
106
107 typ, mt = elem\type!, elem\metatype!
106108
107109 if @metatype and not casts[@metatype .. mt]
108110 return
109111
110 match = if @type then type == @type else @remember type
112 match = if @type then typ == @type else @remember typ
111113 if match
112 1, seq[i]
114 1, elem
113115
114116 __call: => @@ @metatype, @type, true
115117 __tostring: => "#{@type or 'any'}#{@metatype or ''}"
118
119 --- Predicate function Pattern.
120 --
121 -- Only succeeds for `Result`s whose metatype matches and for which the
122 -- predicate function returns true.
123 --
124 -- @function Predicate
125 -- @tparam ?string metatype `'~', '!' or '='
126 -- @tparam function predicate gets `type` as an argument
127 -- @tparam string name printable alias for error reporting
128 class Predicate extends Pattern
129 new: (@metatype, @fn, @name, @recall=false) =>
130
131 casts = { '!!': true, '==': true, '~~': true, '~=': true }
132 capture: (seq, i) =>
133 elem = seq[i]
134 return unless elem
135
136 typ, mt = elem\type!, elem\metatype!
137
138 if @metatype and not casts[@metatype .. mt]
139 return
140
141 if (@.fn typ) and @remember typ
142 1, elem
143
144 __call: => @@ @metatype, @fn, @name, true
145 __tostring: => "#{@name or '[predicate]'}#{@metatype or ''}"
116146
117147 --- Repeat a pattern.
118148 --
206236 --
207237 -- @function Choice
208238 -- @tparam {Pattern,...} elements the inner patterns
209 -- @tparam ?{string,...} keys the keys to use when capturing matches
210239 class Choice extends Pattern
211240 new: (@elements, @recall=false) =>
212241
260289
261290 --- `Type` shorthands for matching `Constant`s.
262291 --
263 -- Call or index with a string to obtain an `Type` instance.
292 -- Call or index with a type or string to obtain an `Type` instance.
293 -- Call with a function and name to obtain a `Predicate` instance.
264294 -- Call to obtain a wildcard pattern.
265295 --
266296 -- const.bang, const.str, const.num
267297 -- const['midi/message'], const(Primitive 'midi/message')
298 -- const(function(typ) return typ.__class == Array end, "array")
268299 -- const()
269300 --
270301 -- @table const
273304 with v = Type '=', T[key]
274305 @[key] = v
275306
276 __call: (...) => Type '=', ...
307 __call: (t, ...) =>
308 if 'function' == type t
309 Predicate '=', t, ...
310 else
311 Type '=', t, ...
277312 }
278313
279314 --- `Type` shorthands for matching `ValueStream`s and `Constant`s.
280315 --
281316 -- Call or index with a type or string to obtain a `Type` instance.
317 -- Call with a function and name to obtain a `Predicate` instance.
282318 -- Call to obtain a wildcard pattern.
283319 --
284320 -- sig.str, sig.num
285321 -- sig['vec3'], sig(T.vec3)
322 -- sig(function(typ) return typ.__class == Array end, "array")
286323 -- sig()
287324 --
288325 -- @table sig
291328 with v = Type '~', T[key]
292329 @[key] = v
293330
294 __call: (...) => Type '~', ...
331 __call: (t, ...) =>
332 if 'function' == type t
333 Predicate '~', t, ...
334 else
335 Type '~', t, ...
295336 }
296337
297338 --- `Type` shorthands for matching `EvtStream`s.
298339 --
299340 -- Call or index with a type or string to obtain an `Type` instance.
341 -- Call with a function and name to obtain a `Predicate` instance.
300342 -- Call to obtain a wildcard pattern.
301343 --
302344 -- evt.bang, evt.str, evt.num
303345 -- evt['midi/message'], evt(Primitive 'midi/message')
346 -- evt(function(typ) return typ.__class == Struct end, "struct")
304347 -- evt()
305348 --
306349 -- @table evt
309352 with v = Type '!', T[key]
310353 @[key] = v
311354
312 __call: (...) => Type '!', ...
355 __call: (t, ...) =>
356 if 'function' == type t
357 Predicate '!', t, ...
358 else
359 Type '!', t, ...
313360 }
314361
315362 --- `Type` shorthands for matching any `Result`s.
316363 --
317364 -- Call or index with a type or string to obtain an `Type` instance.
365 -- Call with a function and name to obtain a `Predicate` instance.
318366 -- Call to obtain a wildcard pattern.
319367 --
320368 -- any.bang, any.str, any.num
321369 -- any['midi/message'], any(Primitive 'midi/message')
370 -- any(function(typ) return typ.__class == Array end, "array")
322371 -- any()
323372 --
324373 -- @table any
327376 with v = Type nil, T[key]
328377 @[key] = v
329378
330 __call: (...) => Type nil, ...
379 __call: (t, ...) =>
380 if 'function' == type t
381 Predicate nil, t, ...
382 else
383 Type nil, t, ...
331384 }
332385
333386 {
334 :Type, :Repeat, :Sequence, :Choice, :Optional
387 :Type, :Predicate, :Repeat, :Sequence, :Choice, :Optional
335388 :const, :sig, :evt, :any
336389 }
2828 assert.has.error -> const!\match { num }
2929 assert.has.error -> evt!\match { str }
3030 assert.has.error -> evt!\match { num }
31 assert.is.equal str, any!\match { str }
32 assert.is.equal num, any!\match { num }
3133
3234 str = mk_evt 'str'
3335 num = mk_evt 'num'
3739 assert.has.error -> const!\match { num }
3840 assert.is.equal str, evt!\match { str }
3941 assert.is.equal num, evt!\match { num }
42 assert.is.equal str, any!\match { str }
43 assert.is.equal num, any!\match { num }
44 assert.is.equal str, any!\match { str }
45 assert.is.equal num, any!\match { num }
4046
4147 str = mk_const 'str'
4248 num = mk_const 'num'
4652 assert.is.equal num, const!\match { num }
4753 assert.has.error -> evt!\match { str }
4854 assert.has.error -> evt!\match { num }
55 assert.is.equal str, any!\match { str }
56 assert.is.equal num, any!\match { num }
57 assert.is.equal str, any!\match { str }
58 assert.is.equal num, any!\match { num }
4959
5060 it 'can recall the type', ->
5161 value = sig!!
5262 event = evt!!
63 thing = any!!
5364 two_equal_values = value + value
5465 two_equal_events = event + event
66 two_equal_things = thing + thing
5567
5668 str1 = mk_val 'str'
5769 str2 = mk_val 'str'
5971 assert.is.same { str1, str2 }, two_equal_values\match { str1, str2 }
6072 assert.is.same { str2, str1 }, two_equal_values\match { str2, str1 }
6173 assert.is.same { num, num }, two_equal_values\match { num, num }
74 assert.is.same { str1, str2 }, two_equal_things\match { str1, str2 }
75 assert.is.same { str2, str1 }, two_equal_things\match { str2, str1 }
76 assert.is.same { num, num }, two_equal_things\match { num, num }
6277 assert.has.error -> two_equal_values\match { str1, num }
6378 assert.has.error -> two_equal_values\match { num, str2 }
79 assert.has.error -> two_equal_things\match { str1, num }
80 assert.has.error -> two_equal_things\match { num, str2 }
6481 assert.has.error -> two_equal_events\match { str1, str2 }
6582
6683 str1 = mk_evt 'str'
6986 assert.is.same { str1, str2 }, two_equal_events\match { str1, str2 }
7087 assert.is.same { str2, str1 }, two_equal_events\match { str2, str1 }
7188 assert.is.same { num, num }, two_equal_events\match { num, num }
89 assert.is.same { str1, str2 }, two_equal_things\match { str1, str2 }
90 assert.is.same { str2, str1 }, two_equal_things\match { str2, str1 }
91 assert.is.same { num, num }, two_equal_things\match { num, num }
7292 assert.has.error -> two_equal_events\match { str1, num }
7393 assert.has.error -> two_equal_events\match { num, str2 }
94 assert.has.error -> two_equal_things\match { str1, num }
95 assert.has.error -> two_equal_things\match { num, str2 }
7496 assert.has.error -> two_equal_values\match { str1, str2 }
7597
7698 it 'stringifies well', ->
7799 assert.is.equal 'any=', tostring const!
78100 assert.is.equal 'any!', tostring evt!
79101 assert.is.equal 'any~', tostring sig!
102 assert.is.equal 'any', tostring any!
80103
81104 describe 'typed shorthand', ->
82105 it 'matches by metatype', ->
88111 assert.has.error -> const.num\match { num }
89112 assert.has.error -> evt.str\match { str }
90113 assert.has.error -> evt.num\match { num }
114 assert.is.equal str, any.str\match { str }
115 assert.is.equal num, any.num\match { num }
91116
92117 str = mk_evt 'str'
93118 num = mk_evt 'num'
97122 assert.has.error -> const.num\match { num }
98123 assert.is.equal str, evt.str\match { str }
99124 assert.is.equal num, evt.num\match { num }
125 assert.is.equal str, any.str\match { str }
126 assert.is.equal num, any.num\match { num }
100127
101128 str = mk_const 'str'
102129 num = mk_const 'num'
106133 assert.is.equal num, const.num\match { num }
107134 assert.has.error -> evt.str\match { str }
108135 assert.has.error -> evt.num\match { num }
136 assert.is.equal str, any.str\match { str }
137 assert.is.equal num, any.num\match { num }
109138
110139 it 'matches by type', ->
111140 str = mk_const 'str'
142171 assert.is.equal 'num~', tostring sig.num
143172 assert.is.equal 'str=', tostring const.str
144173 assert.is.equal 'num=', tostring const.num
174
175 describe 'predicate shorthand', ->
176 sig_str = sig ((typ) -> typ == T.str), "str"
177 sig_num = sig ((typ) -> typ == T.num), "num"
178 const_str = const ((typ) -> typ == T.str), "str"
179 const_num = const ((typ) -> typ == T.num), "num"
180 evt_str = evt ((typ) -> typ == T.str), "str"
181 evt_num = evt ((typ) -> typ == T.num), "num"
182 any_str = any ((typ) -> typ == T.str), "str"
183 any_num = any ((typ) -> typ == T.num), "num"
184
185 it 'matches by metatype', ->
186 str = mk_val 'str'
187 num = mk_val 'num'
188 assert.is.equal str, sig_str\match { str }
189 assert.is.equal num, sig_num\match { num }
190 assert.has.error -> const_str\match { str }
191 assert.has.error -> const_num\match { num }
192 assert.has.error -> evt_str\match { str }
193 assert.has.error -> evt_num\match { num }
194 assert.is.equal str, any_str\match { str }
195 assert.is.equal num, any_num\match { num }
196
197 str = mk_evt 'str'
198 num = mk_evt 'num'
199 assert.has.error -> sig_str\match { str }
200 assert.has.error -> sig_num\match { num }
201 assert.has.error -> const_str\match { str }
202 assert.has.error -> const_num\match { num }
203 assert.is.equal str, evt_str\match { str }
204 assert.is.equal num, evt_num\match { num }
205 assert.is.equal str, any_str\match { str }
206 assert.is.equal num, any_num\match { num }
207
208 str = mk_const 'str'
209 num = mk_const 'num'
210 assert.is.equal str, sig_str\match { str }
211 assert.is.equal num, sig_num\match { num }
212 assert.is.equal str, const_str\match { str }
213 assert.is.equal num, const_num\match { num }
214 assert.has.error -> evt_str\match { str }
215 assert.has.error -> evt_num\match { num }
216 assert.is.equal str, any_str\match { str }
217 assert.is.equal num, any_num\match { num }
218
219 it 'matches by type', ->
220 str = mk_const 'str'
221 num = mk_const 'num'
222 assert.is.equal str, sig_str\match { str }
223 assert.is.equal num, sig_num\match { num }
224 assert.is.equal str, const_str\match { str }
225 assert.is.equal num, const_num\match { num }
226 assert.is.equal str, any_str\match { str }
227 assert.is.equal num, any_num\match { num }
228 assert.has.error -> sig_num\match { str }
229 assert.has.error -> sig_str\match { num }
230
231 str = mk_val 'str'
232 num = mk_val 'num'
233 assert.is.equal str, sig_str\match { str }
234 assert.is.equal num, sig_num\match { num }
235 assert.has.error -> const_num\match { str }
236 assert.has.error -> const_str\match { num }
237 assert.has.error -> sig_num\match { str }
238 assert.has.error -> sig_str\match { num }
239
240 str = mk_evt 'str'
241 num = mk_evt 'num'
242 assert.is.equal str, evt_str\match { str }
243 assert.is.equal num, evt_num\match { num }
244 assert.has.error -> const_num\match { str }
245 assert.has.error -> const_str\match { num }
246 assert.has.error -> evt_num\match { str }
247 assert.has.error -> evt_str\match { num }
248
249 assert.has.error -> any_str\match { num }
145250
146251 describe 'choice', ->
147252 str = mk_val 'str'