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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c10eb07ed10cdcc7fd01fda3b2dccf42786db60f
4
- data.tar.gz: 72b0ecfd3d3ce1bc20c5683adeabb3d2b5915bfe
3
+ metadata.gz: 2f929febec0436c6ff1ddacdefe7936cd29be50d
4
+ data.tar.gz: 929a7fad56a10ef56de4dd09c9309d138fc92b85
5
5
  SHA512:
6
- metadata.gz: 3d1dfceee22b44ed971953d37d3cb9e8e5caf03a2cdbda3be251c9e778f1a5e3ae7be41f2dfc17f3ea1ba7dc63f5a908ff481571957fe18b6267d4670f8d8be7
7
- data.tar.gz: a0ed769069be44d01001a2657a07db0aa3ad3d184afb290d38bc2a82c0c72237737867f972380cc496689f4ee9169f1b3b6081eea7a6a792976c1a10b1621f7c
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/blog/categories/algebrick/>
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.6.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("#{root}/*.in.rb")
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
- require File.join(root, 'init.rb')
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:0x007fafcc96f6a8>
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
@@ -39,9 +39,6 @@
39
39
 
40
40
  # TODO maybe should behave as monad
41
41
 
42
- # TODO anonymous types ? missing tests
43
-
44
-
45
42
  # Provides Algebraic types and pattern matching
46
43
  #
47
44
  # **Quick example**
@@ -39,7 +39,7 @@ module Algebrick
39
39
  end
40
40
 
41
41
  def to_s
42
- name
42
+ name || 'nameless-atom'
43
43
  end
44
44
 
45
45
  def pretty_print(q)
@@ -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 matcher, block if matcher === value
36
+ return true, Matching.match_value(matcher, block) if matcher === value
31
37
  end
32
- raise "no match for (#{value.class}) '#{value}' by any of #{cases.map(&:first).join ', '}"
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 = false
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 unless v == self } if @variants
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.name
140
+ sub_type variant
141
141
  end
142
142
  end.join(' | ') +
143
143
  ')'
144
144
  when :variant
145
- "#{name}(#{variants.map(&:name).join ' | '})"
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 }
@@ -26,7 +26,7 @@ module Algebrick
26
26
  end
27
27
 
28
28
  def name
29
- super || @name || 'NoName'
29
+ super || @name || nil
30
30
  end
31
31
 
32
32
  def to_m(*args)
@@ -32,27 +32,39 @@ module Algebrick
32
32
  variants TrueClass, FalseClass
33
33
  end
34
34
 
35
- LinkedList = Algebrick.type(:value_type) do |list|
35
+ List = Algebrick.type(:value_type) do |list|
36
36
  fields! value: :value_type, next: list
37
- variants EmptyLinkedList = atom, list
37
+ variants EmptyList = atom, list
38
38
  end
39
39
 
40
- module LinkedList
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 LinkedListEmpty === it
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 != EmptyLinkedList
57
+ self.next != EmptyList
58
+ end
59
+
60
+ def empty?
61
+ !next?
54
62
  end
55
- end
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
@@ -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.6.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-01-12 00:00:00.000000000 Z
11
+ date: 2015-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest