algebrick 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/doc/format.rb +3 -2
  4. metadata +4 -6
  5. data/spec/algebrick_test.rb +0 -780
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f929febec0436c6ff1ddacdefe7936cd29be50d
4
- data.tar.gz: 929a7fad56a10ef56de4dd09c9309d138fc92b85
3
+ metadata.gz: 9299bb7379e63fdda3b5b346abca387c4151b429
4
+ data.tar.gz: b93d3b9515e9298a4b1d2dd3a67974ea30649986
5
5
  SHA512:
6
- metadata.gz: f2c50e7f1fc3777edb0743ba8da7ed2096424576701f16236f41e9aef8efd60a234f2a587d2b97dbd1fffc0953d8242cb0880688c0b2922af4a25c3da1a8d537
7
- data.tar.gz: eb8666dbb9f3908dec24a4e300a9cfe6a00bb7d7ef2d4ae1c3bf1f4a6f992f760a4904748f5ab44a6da866c94754aad810cec7987cd67505f2ff39374424f439
6
+ metadata.gz: 6d7d6ac6ff9dd5c1f6f04314271ae2a487cce7cf175d99139934e5355f840765b627342c63c1ba36cdad0865f75fa2d1ec05fb27745426b45627f9a64fc05e42
7
+ data.tar.gz: 25875464076bdc7b603ac3586bd45a982c1a92d325ad8d0ee9a6625ba77e4b85c2d637cf8d3a9dd106ae4be8773fc8c00d93056828adf7376ed86e4b4f834b2e
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.7.1
@@ -3,8 +3,9 @@ require 'bundler/setup'
3
3
  require 'pry'
4
4
  require 'pp'
5
5
 
6
+ root = File.dirname(File.expand_path(Process.argv0))
6
7
  input_paths = if ARGV.empty?
7
- Dir.glob("#{File.dirname(__FILE__)}/*.in.rb")
8
+ Dir.glob("#{root}/*.in.rb")
8
9
  else
9
10
  ARGV
10
11
  end.map { |p| File.expand_path p }
@@ -12,7 +13,7 @@ input_paths = if ARGV.empty?
12
13
  input_paths.each_with_index do |input_path, i|
13
14
 
14
15
  pid = fork do
15
- require_relative 'init.rb'
16
+ require File.join(root, 'init.rb')
16
17
 
17
18
  begin
18
19
  output_path = input_path.gsub /\.in\.rb$/, '.out.rb'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algebrick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Petr Chalupa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-20 00:00:00.000000000 Z
11
+ date: 2015-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -214,7 +214,6 @@ files:
214
214
  - lib/algebrick/type_check.rb
215
215
  - lib/algebrick/types.rb
216
216
  - lib/algebrick/value.rb
217
- - spec/algebrick_test.rb
218
217
  homepage: https://github.com/pitr-ch/algebrick
219
218
  licenses:
220
219
  - Apache License 2.0
@@ -235,10 +234,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
234
  version: '0'
236
235
  requirements: []
237
236
  rubyforge_project:
238
- rubygems_version: 2.2.2
237
+ rubygems_version: 2.4.5
239
238
  signing_key:
240
239
  specification_version: 4
241
240
  summary: Algebraic types and pattern matching for Ruby
242
- test_files:
243
- - spec/algebrick_test.rb
241
+ test_files: []
244
242
  has_rdoc:
@@ -1,780 +0,0 @@
1
- # Copyright 2013 Petr Chalupa <git@pitr.ch>
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- require 'bundler/setup'
16
- require 'minitest/autorun'
17
- require 'minitest/reporters'
18
- MiniTest::Reporters.use!
19
-
20
- require 'pp'
21
- require 'algebrick'
22
- require 'pry'
23
-
24
- class Module
25
- # Return any modules we +extend+
26
- def extended_modules
27
- class << self
28
- self
29
- end.included_modules
30
- end
31
- end
32
-
33
- describe 'AlgebrickTest' do
34
- i_suck_and_my_tests_are_order_dependent!
35
-
36
- Algebrick.types do
37
- Tree = type do |tree|
38
- Empty = type
39
- Leaf = type { fields Integer }
40
- Node = type { fields tree, tree }
41
-
42
- variants Empty, Leaf
43
- end
44
-
45
- Tree.set_variants Node
46
-
47
- BTree = type do |btree|
48
- fields! value: Comparable, left: btree, right: btree
49
- variants Empty, btree
50
- end
51
- end
52
-
53
- module Tree
54
- def a
55
- :a
56
- end
57
-
58
- def depth
59
- case self
60
- when Empty
61
- 0
62
- when Leaf
63
- 1
64
- when Node
65
- left, right = *self
66
- 1 + [left.depth, right.depth].max
67
- end
68
- end
69
-
70
- def each(&block)
71
- return to_enum :each unless block
72
- case self
73
- when Empty
74
- when Leaf
75
- block.call self.value
76
- when Node
77
- left, right = *self
78
- left.each &block
79
- right.each &block
80
- end
81
- end
82
-
83
- def sum
84
- each.inject(0) { |sum, v| sum + v }
85
- end
86
- end
87
-
88
- List = Algebrick.type do |list|
89
- variants Empty, list
90
- fields Integer, list
91
- end
92
-
93
- describe 'type definition' do
94
- module Asd
95
- C = Algebrick.type
96
- D = Algebrick.type
97
- B = Algebrick.type { variants C, D }
98
- end
99
-
100
- it 'asd' do
101
- assert Asd::B
102
- end
103
- end
104
-
105
- describe 'type.to_s' do
106
- it { Empty.to_s.must_equal 'Empty' }
107
- it { Node.to_s.must_equal 'Node(Tree, Tree)' }
108
- it { Leaf.to_s.must_equal 'Leaf(Integer)' }
109
- it { Tree.to_s.must_equal 'Tree(Empty | Leaf | Node)' }
110
- it { List.to_s.must_equal 'List(Empty | List(Integer, List))' }
111
- end
112
-
113
- describe 'atom' do
114
- it { Empty.must_be_kind_of Algebrick::Type }
115
- it { Empty.must_be_kind_of Algebrick::Value }
116
- it { assert Empty.kind_of? Empty }
117
-
118
- it { assert Empty == Empty }
119
- it { assert Empty === Empty }
120
- it { eval(Empty.to_s).must_equal Empty }
121
- it { eval(Empty.inspect).must_equal Empty }
122
- end
123
-
124
- describe 'product' do
125
- it { Leaf[1].must_be_kind_of Algebrick::Value }
126
- it { Leaf.must_be_kind_of Algebrick::Type }
127
- it { Leaf[1].wont_be_kind_of Algebrick::Type }
128
- it { Leaf.wont_be_kind_of Algebrick::Value }
129
-
130
- it { assert Leaf[1] == Leaf[1] }
131
- it { assert Leaf[1] != Leaf[0] }
132
- it { assert Leaf === Leaf[1] }
133
- it { assert Leaf[1].kind_of? Leaf }
134
- it { eval(Leaf[1].to_s).must_equal Leaf[1] }
135
- it { eval(Leaf[1].inspect).must_equal Leaf[1] }
136
- it { eval(Node[Leaf[1], Empty].to_s).must_equal Node[Leaf[1], Empty] }
137
- it { eval(Node[Leaf[1], Empty].inspect).must_equal Node[Leaf[1], Empty] }
138
-
139
- it 'field assign' do
140
- value = Leaf[1].value
141
- value.must_equal 1
142
-
143
- left, right = *Node[Empty, Leaf[1]]
144
- left.must_equal Empty
145
- right.must_equal Leaf[1]
146
-
147
- lambda { Node[Empty, Empty].value }.must_raise NoMethodError
148
- end
149
-
150
- it 'can be marshaled' do
151
- dump = Marshal.dump(leaf = Leaf[1])
152
- assert_equal Marshal.load(dump), leaf
153
- end
154
-
155
- it { lambda { Leaf['a'] }.must_raise TypeError }
156
- it { lambda { Leaf[nil] }.must_raise TypeError }
157
- it { lambda { Node['a'] }.must_raise TypeError }
158
- ComparableItem = Class.new { include Comparable }
159
- it { BTree[1.0, Empty, Empty] }
160
- it { BTree['s', Empty, Empty] }
161
- it { BTree[ComparableItem.new, Empty, Empty] }
162
- it { lambda { BTree[Object.new, Empty, Empty] }.must_raise TypeError }
163
- it { lambda { Node[Empty, nil] }.must_raise TypeError }
164
-
165
- describe 'named field' do
166
- Named = Algebrick.type do
167
- fields! a: Integer, b: Object
168
- end
169
-
170
- it { -> { Named[:a, 1] }.must_raise TypeError }
171
- it { Named[1, :a][:a].must_equal 1 }
172
- it { Named[1, :a][:b].must_equal :a }
173
- it { Named[a: 1, b: :a][:a].must_equal 1 }
174
- it { Named[b: :a, a: 1][:a].must_equal 1 }
175
- it { Named[a: 1, b: :a][:b].must_equal :a }
176
- it { Named[a: 1, b: 2].to_s.must_equal 'Named[a: 1, b: 2]' }
177
- it { Named[a: 1, b: 2].a.must_equal 1 }
178
- it { Named[a: 1, b: 2].b.must_equal 2 }
179
- end
180
-
181
- it { Named[1, :a].to_hash.must_equal a: 1, b: :a }
182
- it { Named[1, Node[Empty, Empty]].to_hash.must_equal a: 1, b: Node[Empty, Empty] }
183
- end
184
-
185
- describe 'variant' do
186
- it { Tree.must_be_kind_of Algebrick::Type }
187
- it { Empty.must_be_kind_of Tree }
188
- it { Empty.a.must_equal :a }
189
- it { Leaf[1].must_be_kind_of Tree }
190
- it { Leaf[1].a.must_equal :a }
191
- it { Node[Empty, Empty].must_be_kind_of Tree }
192
- it { assert Empty.kind_of? List }
193
-
194
- it { assert Empty > List }
195
- it { assert Leaf > Tree }
196
- it { assert Node > Tree }
197
-
198
- it { assert Tree === Empty }
199
- it { assert Tree === Leaf[1] }
200
-
201
- describe 'inherit behavior deep' do
202
- module Deep
203
- B1 = Algebrick.type
204
- B2 = Algebrick.type
205
- A1 = Algebrick.type { variants B1, B2 }
206
- A2 = Algebrick.type
207
- A = Algebrick.type { variants A1, A2 }
208
-
209
- module A
210
- def a
211
- :a
212
- end
213
- end
214
- end
215
-
216
- it { Deep::B1.a.must_equal :a }
217
- it { Deep::B1 > Deep::A }
218
- end
219
-
220
- describe 'a klass as a variant' do
221
- MaybeString = Algebrick.type { variants Empty, String }
222
- it { 'a'.must_be_kind_of MaybeString }
223
- end
224
- end
225
-
226
- describe 'product_variant' do
227
- it { List[1, Empty].must_be_kind_of Algebrick::Value }
228
- it { List.must_be_kind_of Algebrick::Type }
229
-
230
- it { List[1, Empty].must_be_kind_of List }
231
- it { List[1, List[1, Empty]].must_be_kind_of List }
232
- it { Empty.must_be_kind_of List }
233
-
234
- it { assert List[1, Empty] == List[1, Empty] }
235
- it { assert List[1, Empty] != List[2, Empty] }
236
- it { assert List === List[1, Empty] }
237
- it { assert List === Empty }
238
- it { assert List[1, Empty].kind_of? List }
239
- end
240
-
241
- describe 'inspecting' do
242
- let :tree do
243
- tree = Node[Leaf[1], Node[Leaf[2], Empty]]
244
- tree = Node[tree, tree]
245
- Node[tree, tree]
246
- end
247
-
248
- it { tree.to_s.must_equal 'Node[Node[Node[Leaf[1], Node[Leaf[2], Empty]], Node[Leaf[1], Node[Leaf[2], Empty]]], Node[Node[Leaf[1], Node[Leaf[2], Empty]], Node[Leaf[1], Node[Leaf[2], Empty]]]]' }
249
- it { tree.inspect.must_equal tree.to_s }
250
- it do
251
- tree.pretty_inspect.must_equal <<-TXT
252
- Node[
253
- Node[
254
- Node[Leaf[1], Node[Leaf[2], Empty]],
255
- Node[Leaf[1], Node[Leaf[2], Empty]]],
256
- Node[
257
- Node[Leaf[1], Node[Leaf[2], Empty]],
258
- Node[Leaf[1], Node[Leaf[2], Empty]]]]
259
- TXT
260
- end
261
-
262
- let :named do
263
- n = Named[-1, 'as'*40]
264
- 4.times do |i|
265
- n = Named[i, n]
266
- end
267
- n
268
- end
269
-
270
- it { named.to_s.must_equal 'Named[a: 3, b: Named[a: 2, b: Named[a: 1, b: Named[a: 0, b: Named[a: -1, b: asasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasas]]]]]' }
271
- it { named.inspect.must_equal named.to_s }
272
- it do
273
- named.pretty_inspect.must_equal <<-TXT
274
- Named[
275
- a: 3,
276
- b:
277
- Named[
278
- a: 2,
279
- b:
280
- Named[
281
- a: 1,
282
- b:
283
- Named[
284
- a: 0,
285
- b:
286
- Named[
287
- a: -1,
288
- b:
289
- "asasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasasas"]]]]]
290
- TXT
291
- end
292
-
293
- #it do
294
- # PTree[Integer].pretty_inspect.must_equal ''
295
- #end
296
-
297
- end
298
-
299
- describe 'module including' do
300
- type = Algebrick.type { fields Numeric }
301
- type.module_eval do
302
- include Comparable
303
-
304
- def <=>(other)
305
- value <=> other.value
306
- end
307
- end
308
- it 'compares' do
309
- type
310
- assert type[1] < type[2]
311
- end
312
- end
313
-
314
-
315
- describe 'tree' do
316
- it { assert Leaf > Tree }
317
- end
318
-
319
- describe '#depth' do
320
- it do
321
- tree = Node[Node[Empty, Leaf[1]], Leaf[1]]
322
- tree.depth.must_equal 3
323
- end
324
- it do
325
- tree = Node[Empty, Leaf[1]]
326
- tree.depth.must_equal 2
327
- end
328
- it do
329
- tree = Empty
330
- tree.depth.must_equal 0
331
- end
332
- end
333
-
334
- describe '#sum' do
335
- it do
336
- tree = Node[Node[Empty, Leaf[1]], Leaf[1]]
337
- tree.sum.must_equal 2
338
- end
339
- end
340
-
341
- describe 'maybe' do
342
- Maybe = Algebrick.type do
343
- variants None = atom,
344
- Some = type { fields Object }
345
- end
346
-
347
- module Maybe
348
- def maybe(&block)
349
- case self
350
- when None
351
- when Some
352
- block.call self.value
353
- end
354
- end
355
- end
356
-
357
- it { refute None.maybe { true } }
358
- it { assert Some[nil].maybe { true } }
359
- end
360
-
361
- describe 'parametrized types' do
362
-
363
- PTree = Algebrick.type(:v) do |p_tree|
364
- PEmpty = atom
365
- PLeaf = type(:v) { fields value: :v }
366
- PNode = type(:v) { fields left: p_tree, right: p_tree }
367
-
368
- variants PEmpty, PLeaf, PNode
369
- end
370
-
371
- module PTree
372
- def depth
373
- match self,
374
- PEmpty >> 0,
375
- PLeaf >> 1,
376
- PNode.(~any, ~any) >-> left, right do
377
- 1 + [left.depth, right.depth].max
378
- end
379
- end
380
- end
381
-
382
- PTree[String].module_eval do
383
- def glue
384
- match self,
385
- PEmpty >> '',
386
- PLeaf.(value: ~any) >-> v { v },
387
- PNode.(~any, ~any) >-> l, r { l.glue + r.glue }
388
- end
389
- end
390
-
391
- it { [PTree, PLeaf, PNode].all? { |pt| pt > Algebrick::ParametrizedType } }
392
-
393
- it { PLeaf[Integer].to_s.must_equal 'PLeaf[Integer](value: Integer)' }
394
- it { PNode[Integer].to_s.must_equal 'PNode[Integer](left: PTree[Integer], right: PTree[Integer])' }
395
- it { PTree[Integer].to_s.must_equal 'PTree[Integer](PEmpty | PLeaf[Integer] | PNode[Integer])' }
396
-
397
- it { PLeaf[Integer].is_a? PLeaf }
398
- it { PLeaf[Integer][1].is_a? PLeaf }
399
-
400
- it { PLeaf[Integer][1].is_a? Tree }
401
- it { PLeaf[Integer][1].to_s.must_equal 'PLeaf[Integer][value: 1]' }
402
- it { PLeaf[Integer][1].value.must_equal 1 }
403
- it { PNode[Integer][PEmpty, PLeaf[Integer][1]].is_a? Tree }
404
-
405
- it { PLeaf[Integer][2].depth.must_equal 1 }
406
- it do
407
- PTree[Object] # FIXME without this it does not work
408
- PLeaf[Object][2].depth.must_equal 1
409
- end
410
- it do
411
- PNode[Integer][PLeaf[Integer][2],
412
- PEmpty].depth.must_equal 2
413
- end
414
- it do
415
- PTree[String]
416
- PNode[String][PLeaf[String]['a'],
417
- PNode[String][PLeaf[String]['b'],
418
- PEmpty]].glue.must_equal 'ab'
419
- refute PTree[Object].respond_to? :glue
420
- end
421
- end
422
-
423
- extend Algebrick::Matching
424
- include Algebrick::Matching
425
-
426
- describe 'matchers' do
427
- it 'assigns' do
428
- m = ~Empty
429
- m === 2
430
- m.assigns.must_equal [nil]
431
- m === Empty
432
- m.assigns.must_equal [Empty]
433
-
434
- m = ~String.to_m
435
- m === 2
436
- m.assigns.must_equal [nil]
437
- m === 'a'
438
- m.assigns.must_equal %w(a)
439
-
440
- m = ~Leaf.(~any)
441
- m === Leaf[5]
442
- m.assigns.must_equal [Leaf[5], 5]
443
- m === Leaf[3]
444
- m.assigns.must_equal [Leaf[3], 3]
445
-
446
- m = BTree.(value: ~any)
447
- m === BTree[1, Empty, Empty]
448
- m.assigns.must_equal [1]
449
- end
450
-
451
- it 'assigns in case' do
452
- case Leaf[5]
453
- when m = ~Leaf.(~any)
454
- m.assigns.must_equal [Leaf[5], 5]
455
- m.assigns do |leaf, value|
456
- leaf.must_equal Leaf[5]
457
- value.must_equal 5
458
- end
459
- else
460
- raise
461
- end
462
- end
463
-
464
- describe 'match' do
465
- it 'returns value from executed block' do
466
- r = Algebrick.match Empty,
467
- Empty >-> { 1 }
468
- r.must_equal 1
469
- r = Algebrick.match(Empty,
470
- on(Empty) { 1 })
471
- r.must_equal 1
472
- end
473
-
474
- it 'passes assigned values' do
475
- v = Algebrick.match Leaf[5],
476
- Leaf.(~any).case { |value| value }
477
- v.must_equal 5
478
-
479
- v = Algebrick.match Leaf[5],
480
- Leaf.(~any) => -> value { value }
481
- v.must_equal 5
482
-
483
- v = Algebrick.match(Leaf[5],
484
- on(Leaf.(~any)) do |value|
485
- value
486
- end)
487
- v.must_equal 5
488
- end
489
-
490
- it 'raises when no match' do
491
- -> { Algebrick.match Empty,
492
- Leaf.(any) >-> {} }.must_raise RuntimeError
493
- end
494
-
495
- it 'does not pass any values when no matcher' do
496
- Algebrick.match(Empty, on(Empty) { |*a| a }).must_equal []
497
- end
498
-
499
- specify do
500
- assert PTree.match(PEmpty, on(PEmpty, true))
501
- -> { PLeaf.match(PEmpty, on(PEmpty, true)) }.must_raise TypeError
502
-
503
- assert Tree.match(Leaf[1], on(~Leaf) { true })
504
- -> { assert Empty.match(Leaf[1], on(~Leaf) { true }) }.must_raise TypeError
505
- end
506
- end
507
-
508
- describe '#to_s' do
509
- [Empty.to_m,
510
- ~Leaf.(Integer),
511
- ~Empty.to_m,
512
- any,
513
- ~any,
514
- Array.(*any),
515
- Array.(*~any),
516
- Leaf.(any),
517
- ~Leaf.(any),
518
- Node.(Leaf.(any), any),
519
- ~Node.(Leaf.(any), any),
520
- ~Leaf.(1) | Leaf.(~any),
521
- ~Leaf.(1) & Leaf.(~any)
522
- ].each do |matcher|
523
- it matcher.to_s do
524
- eval(matcher.to_s).must_equal matcher
525
- end
526
- end
527
- end
528
-
529
- { Empty.to_m => Empty,
530
- any => Empty,
531
- any => Leaf[1],
532
-
533
- Empty => Empty,
534
- Empty.to_m => Empty,
535
-
536
- Leaf => Leaf[1],
537
- Leaf.(any) => Leaf[5],
538
- Leaf.(~any) => Leaf[5],
539
-
540
- Node => Node[Empty, Empty],
541
- Node.(any, any) => Node[Leaf[1], Empty],
542
- Node.(Empty, any) => Node[Empty, Leaf[1]],
543
- Node.(Leaf.(any), any) => Node[Leaf[1], Empty],
544
- Node.(Leaf.(any), any) => Node[Leaf[1], Empty],
545
-
546
- Tree.to_m => Node[Leaf[1], Empty],
547
- Tree.to_m => Node[Leaf[1], Empty],
548
- Node => Node[Leaf[1], Empty],
549
-
550
- Tree & Leaf.(any) => Leaf[1],
551
- Empty | Leaf.(any) => Leaf[1],
552
- Empty | Leaf.(any) => Empty,
553
- !Empty & Leaf.(any) => Leaf[1],
554
- Empty & !Leaf.(any) => Empty,
555
-
556
- Array.() => [],
557
- Array.(1) => [1],
558
- Array.(Empty, Leaf.(-> v { v > 0 })) => [Empty, Leaf[1]],
559
- Array.(TrueClass) => [true],
560
- Array.(1, *any) => [1],
561
- Array.(1, *any) => [1, 2],
562
- Array.(1, *any) => [1, 2, 3],
563
- Array.(*any) => [1],
564
- Array.(*any) => [1, 2],
565
-
566
- BTree.(value: any) => BTree[1, Empty, Empty],
567
- BTree.(value: 1) => BTree[1, Empty, Empty],
568
- Named.(b: false) => Named[a: 1, b: false],
569
- !Named.(b: false) => Named[a: 1, b: true],
570
-
571
- }.each do |matcher, value|
572
- it "#{matcher} === #{value}" do
573
- assert matcher === value
574
- end
575
- end
576
- end
577
-
578
- it {
579
- assert List.to_m === Empty
580
- assert List === Empty
581
- assert List.to_m === List[1, Empty]
582
- assert List === List[1, Empty]
583
- assert List.(1, any) === List[1, Empty]
584
- refute List.(any, any) === Empty
585
- }
586
-
587
- describe 'and-or matching' do
588
- def assert_assigns(matcher, values)
589
- matcher.assigns.must_equal values
590
- matcher.assigns { |*assigns| assigns.must_equal values }
591
- end
592
-
593
- it do
594
- m = ~Leaf.(->(v) { v > 1 }) & Leaf.(~any)
595
- assert m === Leaf[2]
596
- assert_assigns m, [Leaf[2], 2]
597
- end
598
- it do
599
- m = ~Leaf.(1) | ~Leaf.(~any)
600
- assert m === Leaf[1]
601
- assert_assigns m, [Leaf[1], nil]
602
- end
603
- it do
604
- m = ~Leaf.(~->(v) { v > 1 }.to_m) | ~Leaf.(1)
605
- assert m === Leaf[1]
606
- assert_assigns m, [Leaf[1], nil]
607
- end
608
- it do
609
- m = ~Leaf.(1) | ~Leaf.(~any)
610
- assert m === Leaf[2]
611
- assert_assigns m, [Leaf[2], 2]
612
- end
613
- end
614
-
615
- describe 'equality' do
616
- data = (0..1).map do
617
- [Empty,
618
- Leaf[1],
619
- Node[Empty, Leaf[1]],
620
- Node[Node[Empty, Leaf[1]], Leaf[1]]]
621
- end
622
- data[0].zip(data[1]).each do |tree1, tree2|
623
- it "equals #{tree1}" do
624
- refute tree1.object_id == tree2.object_id, [tree1.object_id, tree2.object_id] unless tree1 == Empty
625
- assert tree1 == tree2
626
- end
627
- end
628
- end
629
-
630
- it 'multi assigns all fields' do
631
- match Node[Empty, Empty],
632
- (on ~Node do |(left, right)|
633
- [left, right].must_equal [Empty, Empty]
634
- end)
635
-
636
- match Leaf[1],
637
- (on ~Leaf do |(v)|
638
- v.must_equal 1
639
- end)
640
-
641
- match Leaf[1],
642
- (on ~Leaf do |v|
643
- v.must_equal Leaf[1]
644
- end)
645
-
646
- match [1, 2],
647
- (on ~Array.(*any) do |(left, right)|
648
- [left, right].must_equal [1, 2]
649
- end)
650
-
651
- match [1, 2],
652
- (on ~Array.to_m do |(left, right)|
653
- [left, right].must_equal [1, 2]
654
- end)
655
-
656
- match [1, 2],
657
- (on ~Array.(*any) do |(left, right)|
658
- [left, right].must_equal [1, 2]
659
- end)
660
-
661
- match [1, 2],
662
- (on (Array.(*~any)) do |(left, right)|
663
- [left, right].must_equal [1, 2]
664
- end)
665
- end
666
-
667
- describe 'list' do
668
- it { List.(any, any) === List[1, Empty] }
669
- it { List.(any, List) === List[1, Empty] }
670
- end
671
-
672
- describe 'LinkedList' do
673
- specify do
674
- Algebrick::List.build(Integer, 1, 2).must_equal(
675
- Algebrick::List[Integer][
676
- value: 1,
677
- next: Algebrick::List[Integer][
678
- value: 2,
679
- next: Algebrick::Types::EmptyList]]
680
- )
681
- assert_equal %w[1 2],
682
- Algebrick::List.build(Integer, 1, 2).map(&:to_s)
683
- end
684
-
685
- TreeList = Algebrick.type do
686
- fields! tag: String, trees: Algebrick::List[Tree]
687
- end
688
-
689
- specify do
690
- assert_equal 'TreeList(tag: String, trees: Algebrick::Types::List[Tree(Empty | Leaf | Node)])',
691
- TreeList.to_s
692
- assert_equal 'TreeList[tag: tag, trees: Algebrick::Types::List[Tree(Empty | Leaf | Node)][value: Node[Empty, Empty], next: Algebrick::Types::EmptyList]]',
693
- TreeList['tag', Algebrick::List.build(Tree, Node[Empty, Empty])].to_s
694
- end
695
- end
696
-
697
- require 'algebrick/serializer'
698
-
699
- describe 'serializer' do
700
- let(:serializer) { Algebrick::Serializer.new }
701
-
702
- it { serializer.dump(Empty).must_equal :algebrick_type => 'Empty' }
703
- it { serializer.dump(Leaf[1]).must_equal :algebrick_type => 'Leaf', :algebrick_fields => [1] }
704
- it { serializer.dump(PLeaf[Integer][1]).must_equal :algebrick_type => 'PLeaf[Integer]', :value => 1 }
705
- it { serializer.dump(Named[1, :a]).must_equal algebrick_type: 'Named', a: 1, b: :a }
706
-
707
- [Empty, Leaf[1], PLeaf[Integer][1], Named[1, :a]].each do |v|
708
- it "serializes and de-serializes #{v}" do
709
- serializer.load(serializer.dump(v)).must_equal v
710
- end
711
- end
712
-
713
- Person = Algebrick.type do |person|
714
- person::Name = type do |name|
715
- variants name::Normal = type { fields String, String },
716
- name::AbNormal = type { fields String, String, String }
717
- end
718
-
719
- person::Address = type do |address|
720
- variants address::Homeless = atom, address
721
- fields street: String,
722
- zip: Integer
723
- end
724
-
725
- fields name: person::Name,
726
- address: person::Address
727
- end
728
-
729
- transformations = [
730
- [{ name: %w(a b), address: 'homeless' },
731
- { algebrick_type: "Person",
732
- name: { algebrick_type: "Person::Name::Normal", algebrick_fields: %w(a b) },
733
- address: { algebrick_type: "Person::Address::Homeless" } },
734
- Person[Person::Name::Normal['a', 'b'], Person::Address::Homeless],
735
- "{\"name\":[\"a\",\"b\"],\"address\":\"homeless\"}"
736
- ],
737
- [{ name: %w(a b c), address: 'homeless', metadata: :ignored },
738
- { algebrick_type: "Person",
739
- name: { algebrick_type: "Person::Name::AbNormal", algebrick_fields: %w(a b c) },
740
- address: { algebrick_type: "Person::Address::Homeless" } },
741
- Person[Person::Name::AbNormal['a', 'b', 'c'], Person::Address::Homeless],
742
- "{\"name\":[\"a\",\"b\",\"c\"],\"address\":\"homeless\",\"metadata\":\"ignored\"}"
743
- ],
744
- [{ name: %w(a b c), address: { street: 'asd', zip: 15 } },
745
- { algebrick_type: "Person",
746
- name: { algebrick_type: "Person::Name::AbNormal", algebrick_fields: %w(a b c) },
747
- address: { algebrick_type: "Person::Address", street: "asd", zip: 15 } },
748
- Person[Person::Name::AbNormal['a', 'b', 'c'], Person::Address['asd', 15]],
749
- "{\"name\":[\"a\",\"b\",\"c\"],\"address\":{\"street\":\"asd\",\"zip\":15}}"
750
- ]
751
- ]
752
-
753
- transformations.each do |_, from, to, _|
754
- it do
755
- serializer.load(from).must_equal to
756
- end
757
- end
758
-
759
- describe 'no name types' do
760
- WithNoName = Algebrick.type do |t|
761
- fields a: String, v: t
762
- variants t,
763
- type { |it| variants TrueClass, FalseClass, it },
764
- type { fields string: String },
765
- atom
766
- end
767
-
768
- it 'prints reasonably' do
769
- assert_equal 'WithNoName(WithNoName(a: String, v: WithNoName) | (TrueClass | FalseClass | (recursive)) | (string: String) | nameless-atom)',
770
- WithNoName.to_s
771
- assert_equal '(TrueClass | FalseClass | (recursive))', WithNoName.variants[1].to_s
772
- assert_equal '(string: String)', WithNoName.variants[2].to_s
773
- assert_equal 'nameless-atom', WithNoName.variants[3].to_s
774
-
775
- end
776
- end
777
-
778
- end
779
-
780
- end