algebrick 0.7.0 → 0.7.1

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 (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