algebrick 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|