algebrick 0.6.0 → 0.7.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/README.md +1 -1
- data/README_FULL.md +5 -0
- data/VERSION +1 -1
- data/doc/format.rb +2 -3
- data/doc/json.out.rb +1 -1
- data/lib/algebrick.rb +0 -3
- data/lib/algebrick/atom.rb +1 -1
- data/lib/algebrick/matching.rb +8 -2
- data/lib/algebrick/product_variant.rb +11 -5
- data/lib/algebrick/type.rb +1 -1
- data/lib/algebrick/types.rb +18 -6
- data/spec/algebrick_test.rb +45 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f929febec0436c6ff1ddacdefe7936cd29be50d
|
4
|
+
data.tar.gz: 929a7fad56a10ef56de4dd09c9309d138fc92b85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2c50e7f1fc3777edb0743ba8da7ed2096424576701f16236f41e9aef8efd60a234f2a587d2b97dbd1fffc0953d8242cb0880688c0b2922af4a25c3da1a8d537
|
7
|
+
data.tar.gz: eb8666dbb9f3908dec24a4e300a9cfe6a00bb7d7ef2d4ae1c3bf1f4a6f992f760a4904748f5ab44a6da866c94754aad810cec7987cd67505f2ff39374424f439
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ It's a gem providing **algebraic types** and **pattern matching** seamlessly int
|
|
6
6
|
|
7
7
|
- Documentation: <http://blog.pitr.ch/algebrick>
|
8
8
|
- Source: <https://github.com/pitr-ch/algebrick>
|
9
|
-
- Blog: <http://blog.pitr.ch/
|
9
|
+
- Blog: <http://blog.pitr.ch/tag/algebrick.html>
|
10
10
|
|
11
11
|
## What is it good for?
|
12
12
|
|
data/README_FULL.md
CHANGED
@@ -80,6 +80,11 @@ They use standard `#===` method to match against values.
|
|
80
80
|
|
81
81
|
## What is it good for?
|
82
82
|
|
83
|
+
### TODO
|
84
|
+
|
85
|
+
- record like structures
|
86
|
+
- creating new types by summing existing
|
87
|
+
|
83
88
|
### Defining data structures
|
84
89
|
|
85
90
|
<!-- {include:file:doc/data.out.rb} -->
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/doc/format.rb
CHANGED
@@ -3,9 +3,8 @@ require 'bundler/setup'
|
|
3
3
|
require 'pry'
|
4
4
|
require 'pp'
|
5
5
|
|
6
|
-
root = File.dirname(File.expand_path(Process.argv0))
|
7
6
|
input_paths = if ARGV.empty?
|
8
|
-
Dir.glob("#{
|
7
|
+
Dir.glob("#{File.dirname(__FILE__)}/*.in.rb")
|
9
8
|
else
|
10
9
|
ARGV
|
11
10
|
end.map { |p| File.expand_path p }
|
@@ -13,7 +12,7 @@ input_paths = if ARGV.empty?
|
|
13
12
|
input_paths.each_with_index do |input_path, i|
|
14
13
|
|
15
14
|
pid = fork do
|
16
|
-
|
15
|
+
require_relative 'init.rb'
|
17
16
|
|
18
17
|
begin
|
19
18
|
output_path = input_path.gsub /\.in\.rb$/, '.out.rb'
|
data/doc/json.out.rb
CHANGED
@@ -20,7 +20,7 @@ require 'algebrick/serializer' # => true
|
|
20
20
|
require 'multi_json' # => true
|
21
21
|
|
22
22
|
# Prepare a message for sending.
|
23
|
-
serializer = Algebrick::Serializer.new # => #<Algebrick::Serializer:
|
23
|
+
serializer = Algebrick::Serializer.new # => #<Algebrick::Serializer:0x007fab42bdf6d8>
|
24
24
|
request = CreateUser[User['root', 'lajDh4']]
|
25
25
|
# => CreateUser[User[login: root, password: lajDh4]]
|
26
26
|
raw_request = MultiJson.dump serializer.dump(request)
|
data/lib/algebrick.rb
CHANGED
data/lib/algebrick/atom.rb
CHANGED
data/lib/algebrick/matching.rb
CHANGED
@@ -20,6 +20,12 @@ module Algebrick
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def match(value, *cases)
|
23
|
+
success, result = match? value, *cases
|
24
|
+
raise "no match for (#{value.class}) '#{value}' by any of #{cases.map(&:first).join ', '}" unless success
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def match?(value, *cases)
|
23
29
|
cases = if cases.size == 1 && cases.first.is_a?(Hash)
|
24
30
|
cases.first
|
25
31
|
else
|
@@ -27,9 +33,9 @@ module Algebrick
|
|
27
33
|
end
|
28
34
|
|
29
35
|
cases.each do |matcher, block|
|
30
|
-
return Matching.match_value
|
36
|
+
return true, Matching.match_value(matcher, block) if matcher === value
|
31
37
|
end
|
32
|
-
|
38
|
+
[false, nil]
|
33
39
|
end
|
34
40
|
|
35
41
|
def on(matcher, value = nil, &block)
|
@@ -25,8 +25,8 @@ module Algebrick
|
|
25
25
|
|
26
26
|
def initialize(name, &definition)
|
27
27
|
super(name, &definition)
|
28
|
-
@to_be_kind_of
|
29
|
-
@final_variants
|
28
|
+
@to_be_kind_of = []
|
29
|
+
@final_variants = false
|
30
30
|
end
|
31
31
|
|
32
32
|
def set_fields(fields_or_hash)
|
@@ -105,7 +105,7 @@ module Algebrick
|
|
105
105
|
def apply_be_kind_of
|
106
106
|
@to_be_kind_of.each do |type|
|
107
107
|
@constructor.send :include, type if @constructor
|
108
|
-
variants.each { |v| v.be_kind_of type
|
108
|
+
variants.each { |v| v.be_kind_of type if v != self && v.respond_to?(:be_kind_of) } if @variants
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -137,12 +137,12 @@ module Algebrick
|
|
137
137
|
if variant == self
|
138
138
|
product_to_s
|
139
139
|
else
|
140
|
-
variant
|
140
|
+
sub_type variant
|
141
141
|
end
|
142
142
|
end.join(' | ') +
|
143
143
|
')'
|
144
144
|
when :variant
|
145
|
-
"#{name}(#{variants.map
|
145
|
+
"#{name}(#{variants.map { |v| sub_type v }.join ' | '})"
|
146
146
|
else
|
147
147
|
raise
|
148
148
|
end
|
@@ -182,6 +182,12 @@ module Algebrick
|
|
182
182
|
"#{name}(#{fields_str.join ', '})"
|
183
183
|
end
|
184
184
|
|
185
|
+
def sub_type(type)
|
186
|
+
return type.name unless type.name.nil?
|
187
|
+
return '(recursive)' if type == self # FIXME: will not catch deeper recursions
|
188
|
+
return type.to_s
|
189
|
+
end
|
190
|
+
|
185
191
|
def add_field_names(names)
|
186
192
|
@field_names = names
|
187
193
|
names.all? { |k| Type! k, Symbol }
|
data/lib/algebrick/type.rb
CHANGED
data/lib/algebrick/types.rb
CHANGED
@@ -32,27 +32,39 @@ module Algebrick
|
|
32
32
|
variants TrueClass, FalseClass
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
List = Algebrick.type(:value_type) do |list|
|
36
36
|
fields! value: :value_type, next: list
|
37
|
-
variants
|
37
|
+
variants EmptyList = atom, list
|
38
38
|
end
|
39
39
|
|
40
|
-
module
|
40
|
+
module List
|
41
41
|
include Enumerable
|
42
42
|
|
43
43
|
def each(&block)
|
44
|
+
return to_enum unless block_given?
|
45
|
+
|
44
46
|
it = self
|
45
47
|
loop do
|
46
|
-
break if
|
48
|
+
break if EmptyList === it
|
47
49
|
block.call it.value
|
48
50
|
it = it.next
|
49
51
|
end
|
52
|
+
|
53
|
+
self
|
50
54
|
end
|
51
55
|
|
52
56
|
def next?
|
53
|
-
self.next !=
|
57
|
+
self.next != EmptyList
|
58
|
+
end
|
59
|
+
|
60
|
+
def empty?
|
61
|
+
!next?
|
54
62
|
end
|
55
|
-
|
63
|
+
|
64
|
+
def self.build(type, *items)
|
65
|
+
items.reverse_each.reduce(EmptyList) { |list, item| self[type][item, list] }
|
66
|
+
end
|
67
|
+
end
|
56
68
|
end
|
57
69
|
|
58
70
|
include Types
|
data/spec/algebrick_test.rb
CHANGED
@@ -669,6 +669,31 @@ Named[
|
|
669
669
|
it { List.(any, List) === List[1, Empty] }
|
670
670
|
end
|
671
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
|
+
|
672
697
|
require 'algebrick/serializer'
|
673
698
|
|
674
699
|
describe 'serializer' do
|
@@ -730,6 +755,26 @@ Named[
|
|
730
755
|
serializer.load(from).must_equal to
|
731
756
|
end
|
732
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
|
+
|
733
778
|
end
|
734
779
|
|
735
780
|
end
|
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.
|
4
|
+
version: 0.7.0
|
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-
|
11
|
+
date: 2015-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|