axiom-types 0.0.5 → 0.1.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.
Files changed (40) hide show
  1. checksums.yaml +5 -13
  2. data/.rubocop.yml +6 -0
  3. data/.travis.yml +11 -8
  4. data/Gemfile +4 -0
  5. data/Gemfile.devtools +27 -13
  6. data/axiom-types.gemspec +6 -3
  7. data/config/flay.yml +1 -1
  8. data/config/flog.yml +1 -1
  9. data/config/reek.yml +10 -3
  10. data/config/rubocop.yml +10 -9
  11. data/lib/axiom/types.rb +5 -3
  12. data/lib/axiom/types/encodable.rb +4 -5
  13. data/lib/axiom/types/length_comparable.rb +12 -5
  14. data/lib/axiom/types/numeric.rb +2 -2
  15. data/lib/axiom/types/object.rb +9 -0
  16. data/lib/axiom/types/support/infinity.rb +31 -48
  17. data/lib/axiom/types/support/options.rb +1 -1
  18. data/lib/axiom/types/type.rb +27 -0
  19. data/lib/axiom/types/value_comparable.rb +11 -6
  20. data/lib/axiom/types/version.rb +1 -1
  21. data/spec/unit/axiom/types/class_methods/finalize_spec.rb +1 -1
  22. data/spec/unit/axiom/types/encodable/class_methods/extended_spec.rb +1 -1
  23. data/spec/unit/axiom/types/encodable/finalize_spec.rb +1 -1
  24. data/spec/unit/axiom/types/infinity/{class_methods/coerce_spec.rb → coerce_spec.rb} +5 -5
  25. data/spec/unit/axiom/types/infinity/{class_methods/spaceship_operator_spec.rb → spaceship_operator_spec.rb} +3 -3
  26. data/spec/unit/axiom/types/infinity/{class_methods/succ_spec.rb → succ_spec.rb} +2 -2
  27. data/spec/unit/axiom/types/length_comparable/class_methods/extended_spec.rb +5 -3
  28. data/spec/unit/axiom/types/length_comparable/finalize_spec.rb +1 -0
  29. data/spec/unit/axiom/types/length_comparable/range_spec.rb +25 -0
  30. data/spec/unit/axiom/types/negative_infinity/{class_methods/spaceship_operator_spec.rb → spaceship_operator_spec.rb} +3 -3
  31. data/spec/unit/axiom/types/object/class_methods/inspect_spec.rb +11 -0
  32. data/spec/unit/axiom/types/options/inherited_spec.rb +1 -1
  33. data/spec/unit/axiom/types/type/class_methods/anonymous_predicate_spec.rb +19 -0
  34. data/spec/unit/axiom/types/type/class_methods/base_predicate_spec.rb +19 -0
  35. data/spec/unit/axiom/types/type/class_methods/base_spec.rb +19 -0
  36. data/spec/unit/axiom/types/type/class_methods/includes_spec.rb +2 -2
  37. data/spec/unit/axiom/types/value_comparable/class_methods/extended_spec.rb +1 -1
  38. data/spec/unit/axiom/types/value_comparable/finalize_spec.rb +1 -0
  39. data/spec/unit/axiom/types/value_comparable/range_spec.rb +25 -0
  40. metadata +51 -24
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OTk1ZjkwNjg3MjZkNzIwNmI5Yzc4YmNlMTQ5NjNlNDhkNWI5Y2EyZg==
5
- data.tar.gz: !binary |-
6
- NTllNTE2NWUzNDUwNGJlODJmODk2NzBiZmM1YmIwYWZlNGM3YzZjNw==
2
+ SHA1:
3
+ metadata.gz: c3f4ab34cb8059c83c6512f6f7e3eaf4516583db
4
+ data.tar.gz: 3b75505765e6c9efe0bedb546350affe457d1419
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- YjJkYjk1OWQ1MmQ5NjVkZWU4Y2FhZjVlY2VlZGFhNzMzYWE3MWZkMjc0MGY4
10
- YmQzYjNiYmIzOGYzMzdjYzUwOTg5NmU5ZTBlN2ZjYjg3MWMxMWYzNTE4ZjA3
11
- ZTQ0ZGI3N2YyM2ZjZGQ4MmQ2ZTA2ZTgwMTA3NmNiZjcxMTYyMTQ=
12
- data.tar.gz: !binary |-
13
- MGQwZmUxMDZhNjhjYWFhNTQ0NjY0ODQ2OGJmMDAwMzI0M2UwMDQ0ODg4OGRm
14
- MzA0ZTkxYjZjNWJkYjMyNjBhZmFkMzE2Yzc4YjA4Zjk0ODI0OGQ3OTcwNjBh
15
- OTIzZGRhODBjZjdlOWJjYTY2YTViYTVkMzY3ZmEyOThmMGU1YTE=
6
+ metadata.gz: f4ae3db9a977137f1d50f696f4c88846b0d9754f6cb34809f1d4772d9aa4f4f32a970a626902df4997873f4b1f059f4e9c2b9eb8988d81ac82f027ecf610d8c6
7
+ data.tar.gz: 913fea68aa5f22cf384e142710ddfeb7f53470f50a85d850d37192c5560902724ffb4c44e80d2cfdac8722ac50656cbb5c928690a27d0a2966b7a33f3fc603f5
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ Includes:
3
+ - 'Gemfile'
4
+ Excludes:
5
+ - 'Gemfile.devtools'
6
+ - 'vendor/**'
@@ -1,23 +1,26 @@
1
1
  language: ruby
2
2
  before_install: gem install bundler
3
3
  bundler_args: --without yard guard benchmarks
4
- script: "bundle exec rake ci"
4
+ script: "bundle exec rake ci:metrics"
5
5
  rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
+ - 2.1.0
8
9
  - ruby-head
9
- - rbx-19mode
10
+ - rbx
10
11
  matrix:
11
12
  include:
12
13
  - rvm: jruby-19mode
13
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
14
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
15
+ - rvm: jruby-20mode
16
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
17
+ - rvm: jruby-21mode
18
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
14
19
  - rvm: jruby-head
15
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
20
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
16
21
  allow_failures:
17
- - rvm: 1.9.3 # mutant fails
18
- - rvm: 2.0.0 # mutant fails
19
- - rvm: ruby-head # travis broken
20
- - rvm: rbx-19mode # mutant fails
22
+ - rvm: 2.1.0 # buggy runtime
23
+ fast_finish: true
21
24
  notifications:
22
25
  irc:
23
26
  channels:
data/Gemfile CHANGED
@@ -4,6 +4,10 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
+ platforms :rbx do
8
+ gem 'rubysl-bigdecimal', '~> 2.0.2'
9
+ end
10
+
7
11
  group :development, :test do
8
12
  gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
9
13
  end
@@ -4,21 +4,24 @@ group :development do
4
4
  gem 'rake', '~> 10.1.0'
5
5
  gem 'rspec', '~> 2.14.1'
6
6
  gem 'yard', '~> 0.8.7'
7
+
8
+ platform :rbx do
9
+ gem 'rubysl-singleton', '~> 2.0.0'
10
+ end
7
11
  end
8
12
 
9
13
  group :yard do
10
- gem 'kramdown', '~> 1.2.0'
14
+ gem 'kramdown', '~> 1.3.0'
11
15
  end
12
16
 
13
17
  group :guard do
14
- gem 'guard', '~> 1.8.1'
15
- gem 'guard-bundler', '~> 1.0.0'
16
- gem 'guard-rspec', '~> 3.0.2'
17
- gem 'guard-rubocop', '~> 0.2.0'
18
- gem 'guard-mutant', '~> 0.0.1'
18
+ gem 'guard', '~> 2.3.0'
19
+ gem 'guard-bundler', '~> 2.0.0'
20
+ gem 'guard-rspec', '~> 4.2.0'
21
+ gem 'guard-rubocop', '~> 1.0.0'
19
22
 
20
23
  # file system change event handling
21
- gem 'listen', '~> 1.3.0'
24
+ gem 'listen', '~> 2.4.0'
22
25
  gem 'rb-fchange', '~> 0.0.6', require: false
23
26
  gem 'rb-fsevent', '~> 0.9.3', require: false
24
27
  gem 'rb-inotify', '~> 0.9.0', require: false
@@ -30,18 +33,29 @@ group :guard do
30
33
  end
31
34
 
32
35
  group :metrics do
33
- gem 'coveralls', '~> 0.6.7'
36
+ gem 'coveralls', '~> 0.7.0'
34
37
  gem 'flay', '~> 2.4.0'
35
- gem 'flog', '~> 4.1.1'
38
+ gem 'flog', '~> 4.2.0'
36
39
  gem 'reek', '~> 1.3.2'
37
- gem 'rubocop', '~> 0.13.0'
38
- gem 'simplecov', '~> 0.7.1'
39
- gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
40
+ gem 'rubocop', '~> 0.16.0'
41
+ gem 'simplecov', '~> 0.8.2'
42
+ gem 'yardstick', '~> 0.9.9'
43
+
44
+ platforms :mri do
45
+ gem 'mutant', '~> 0.3.4'
46
+ end
40
47
 
41
48
  platforms :ruby_19, :ruby_20 do
42
- gem 'mutant', git: 'https://github.com/mbj/mutant.git'
43
49
  gem 'yard-spellcheck', '~> 0.1.5'
44
50
  end
51
+
52
+ platform :rbx do
53
+ gem 'json', '~> 1.8.1'
54
+ gem 'racc', '~> 1.4'
55
+ gem 'rubysl-logger', '~> 2.0.0'
56
+ gem 'rubysl-open-uri', '~> 2.0.0'
57
+ gem 'rubysl-prettyprint', '~> 2.0.2'
58
+ end
45
59
  end
46
60
 
47
61
  group :benchmarks do
@@ -17,8 +17,11 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = `git ls-files -- spec/unit`.split($/)
18
18
  gem.extra_rdoc_files = %w[LICENSE README.md CONTRIBUTING.md TODO]
19
19
 
20
- gem.add_dependency('descendants_tracker', '~> 0.0.1')
21
- gem.add_dependency('ice_nine', '~> 0.9')
20
+ gem.required_ruby_version = '>= 1.9.3'
22
21
 
23
- gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
22
+ gem.add_runtime_dependency('descendants_tracker', '~> 0.0.3')
23
+ gem.add_runtime_dependency('ice_nine', '~> 0.11.0')
24
+ gem.add_runtime_dependency('thread_safe', '~> 0.1.3')
25
+
26
+ gem.add_development_dependency('bundler', '~> 1.5', '>= 1.5.2')
24
27
  end
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 19
3
- total_score: 162
3
+ total_score: 175
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 10.0
2
+ threshold: 11.4
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  Attribute:
3
3
  enabled: true
4
- exclude: []
4
+ exclude:
5
+ - Axiom::Types::LengthComparable
6
+ - Axiom::Types::ValueComparable
5
7
  BooleanParameter:
6
8
  enabled: true
7
9
  exclude: []
@@ -10,7 +12,12 @@ ClassVariable:
10
12
  exclude: []
11
13
  ControlParameter:
12
14
  enabled: true
13
- exclude: []
15
+ exclude:
16
+ - Axiom::Types::Boolean#self.infer_from_primitive_class
17
+ - Axiom::Types::Collection#self.infer_from
18
+ - Axiom::Types::Infinity#<=>
19
+ - Axiom::Types::Object#self.infer_from_primitive_class
20
+ - Axiom::Types::Type#self.infer
14
21
  DataClump:
15
22
  enabled: true
16
23
  exclude: []
@@ -63,7 +70,7 @@ TooManyInstanceVariables:
63
70
  TooManyMethods:
64
71
  enabled: true
65
72
  exclude: []
66
- max_methods: 0
73
+ max_methods: 4
67
74
  TooManyStatements:
68
75
  enabled: true
69
76
  exclude:
@@ -1,11 +1,4 @@
1
- AllCops:
2
- Includes:
3
- - '../**/*.rake'
4
- - 'Gemfile'
5
- - 'Gemfile.devtools'
6
- Excludes:
7
- - '**/vendor/**'
8
- - '**/benchmarks/**'
1
+ inherit_from: ../.rubocop.yml
9
2
 
10
3
  # Avoid parameter lists longer than five parameters.
11
4
  ParameterLists:
@@ -30,7 +23,7 @@ CollectionMethods:
30
23
  # sections of code and visually separate them. When the keyword is at the same
31
24
  # level I think it sort of blends in with the def keywords and makes it harder
32
25
  # to scan the code and see where the sections are.
33
- AccessControl:
26
+ AccessModifierIndentation:
34
27
  Enabled: false
35
28
 
36
29
  # Limit line length
@@ -60,3 +53,11 @@ ConstantName:
60
53
  # Not all trivial readers/writers can be defined with attr_* methods
61
54
  TrivialAccessors:
62
55
  Enabled: false
56
+
57
+ # The #<=> method argument has an underscore because it is not referenced
58
+ OpMethod:
59
+ Enabled: false
60
+
61
+ # Allow empty lines around body
62
+ EmptyLinesAroundBody:
63
+ Enabled: false
@@ -3,9 +3,11 @@
3
3
  require 'bigdecimal'
4
4
  require 'date'
5
5
  require 'set'
6
+ require 'singleton'
6
7
 
7
- require 'ice_nine'
8
8
  require 'descendants_tracker'
9
+ require 'ice_nine'
10
+ require 'thread_safe'
9
11
 
10
12
  module Axiom
11
13
 
@@ -22,7 +24,7 @@ module Axiom
22
24
  Contradiction = ->(_value) { true }.freeze
23
25
 
24
26
  # Cache the type inference lookup by object
25
- @inference_cache = Hash.new do |cache, object|
27
+ @inference_cache = ThreadSafe::Cache.new do |cache, object|
26
28
  type = nil
27
29
  Type.descendants.detect do |descendant|
28
30
  type = descendant.infer(object)
@@ -61,8 +63,8 @@ module Axiom
61
63
  end # module Types
62
64
  end # module Axiom
63
65
 
64
- require 'axiom/types/support/infinity'
65
66
  require 'axiom/types/support/options'
67
+ require 'axiom/types/support/infinity'
66
68
 
67
69
  require 'axiom/types/value_comparable'
68
70
  require 'axiom/types/length_comparable'
@@ -34,7 +34,7 @@ module Axiom
34
34
  # @api private
35
35
  def finalize
36
36
  return self if frozen?
37
- ascii_compatible? ? has_ascii_compatible_encoding : has_encoding
37
+ ascii_compatible? ? use_ascii_compatible_encoding : use_encoding
38
38
  super
39
39
  end
40
40
 
@@ -54,7 +54,7 @@ module Axiom
54
54
  # @return [undefined]
55
55
  #
56
56
  # @api private
57
- def has_ascii_compatible_encoding
57
+ def use_ascii_compatible_encoding
58
58
  constraint do |object|
59
59
  object.encoding.equal?(encoding) || object.to_s.ascii_only?
60
60
  end
@@ -65,11 +65,10 @@ module Axiom
65
65
  # @return [undefined]
66
66
  #
67
67
  # @api private
68
- def has_encoding
68
+ def use_encoding
69
69
  constraint { |object| object.encoding.equal?(encoding) }
70
70
  end
71
71
 
72
- end
73
-
72
+ end # module Encodable
74
73
  end # module Types
75
74
  end # module Axiom
@@ -6,6 +6,13 @@ module Axiom
6
6
  # Add a minimum and maximum length constraint to a type
7
7
  module LengthComparable
8
8
 
9
+ # The range of allowed lengths
10
+ #
11
+ # @return [Range]
12
+ #
13
+ # @api public
14
+ attr_reader :range
15
+
9
16
  # Hook called when module is extended
10
17
  #
11
18
  # Add #minimum_length and #maximum_length DSL methods to descendant.
@@ -19,8 +26,8 @@ module Axiom
19
26
  super
20
27
  descendant.class_eval do
21
28
  accept_options :minimum_length, :maximum_length
22
- minimum_length Infinity
23
- maximum_length NegativeInfinity
29
+ minimum_length Infinity.instance
30
+ maximum_length NegativeInfinity.instance
24
31
  end
25
32
  end
26
33
 
@@ -31,7 +38,8 @@ module Axiom
31
38
  # @api private
32
39
  def finalize
33
40
  return self if frozen?
34
- has_length_within_range
41
+ @range = IceNine.deep_freeze(minimum_length..maximum_length)
42
+ use_length_within_range
35
43
  super
36
44
  end
37
45
 
@@ -44,8 +52,7 @@ module Axiom
44
52
  # @todo freeze the minimum_length and maximum_length
45
53
  #
46
54
  # @api private
47
- def has_length_within_range
48
- range = minimum_length..maximum_length
55
+ def use_length_within_range
49
56
  constraint { |object| range.cover?(object.length) }
50
57
  end
51
58
 
@@ -10,8 +10,8 @@ module Axiom
10
10
  primitive ::Numeric
11
11
  coercion_method :to_numeric
12
12
 
13
- minimum NegativeInfinity
14
- maximum Infinity
13
+ minimum NegativeInfinity.instance
14
+ maximum Infinity.instance
15
15
 
16
16
  end # class Numeric
17
17
  end # module Types
@@ -37,6 +37,15 @@ module Axiom
37
37
  super
38
38
  end
39
39
 
40
+ # The type name and primitive
41
+ #
42
+ # @return [String]
43
+ #
44
+ # @api public
45
+ def self.inspect
46
+ "#{base} (#{primitive})"
47
+ end
48
+
40
49
  # Infer the type if the primitive class matches
41
50
  #
42
51
  # @param [Object] object
@@ -4,8 +4,13 @@ module Axiom
4
4
  module Types
5
5
 
6
6
  # Represent an infinite number
7
- class Infinity < BasicObject
8
- extend ::Comparable
7
+ class Infinity
8
+ extend Options, DescendantsTracker
9
+ include ::Comparable, ::Singleton
10
+
11
+ accept_options :inverse, :number
12
+
13
+ number ::Float::INFINITY
9
14
 
10
15
  # Test the number against infinity
11
16
  #
@@ -17,64 +22,57 @@ module Axiom
17
22
  # returned if the other object is something other than infinity
18
23
  #
19
24
  # @api private
20
- def self.<=>(other)
25
+ def <=>(other)
26
+ klass = self.class
21
27
  case other
22
- when ::BigDecimal then 1
23
- when ->(arg) { arg == number } then 0
24
- when ::Numeric, inverse.singleton_class then 1
28
+ when BigDecimal then 1
29
+ when ->(arg) { arg == klass.number } then 0
30
+ when ::Numeric, klass.inverse then 1
25
31
  end
26
32
  end
27
33
 
28
- # Coerce a number into an Infinity class for comparison
34
+ # Coerce a number into an Infinity instance for comparison
29
35
  #
30
36
  # @param [::Numeric] other
31
37
  #
32
38
  # @return [Array(Infinity, Infinity)]
33
39
  #
34
40
  # @api private
35
- def self.coerce(other)
41
+ def coerce(other)
36
42
  case other
37
- when ::BigDecimal then [inverse, self]
38
- when number then [self, self]
39
- when ::Numeric then [inverse, self]
43
+ when BigDecimal then [inverse, self]
44
+ when self.class.number then [self, self]
45
+ when ::Numeric then [inverse, self]
40
46
  else
41
- raise ::TypeError, "#{other.class} cannot be coerced"
47
+ fail TypeError, "#{other.class} cannot be coerced"
42
48
  end
43
49
  end
44
50
 
45
51
  # Return the next successive object, which is always self
46
52
  #
47
- # @return [Class<Infinity>]
53
+ # @return [Infinity]
48
54
  #
49
55
  # @api private
50
- def self.succ
56
+ def succ
51
57
  self
52
58
  end
53
59
 
54
- # The inverse of infinity
55
- #
56
- # @return [Class<NegativeInfinity>]
57
- #
58
- # @api private
59
- def self.inverse
60
- NegativeInfinity
61
- end
62
- private_class_method :inverse
60
+ private
63
61
 
64
- # The numeric representation of infinity
62
+ # The inverse instance
65
63
  #
66
- # @return [Float]
64
+ # @return [Infinity]
67
65
  #
68
66
  # @api private
69
- def self.number
70
- ::Float::INFINITY
67
+ def inverse
68
+ self.class.inverse.instance
71
69
  end
72
- private_class_method :number
73
70
 
74
71
  end # class Infinity
75
72
 
76
73
  # Represent a negative infinite number
77
74
  class NegativeInfinity < Infinity
75
+ number(-::Float::INFINITY)
78
76
 
79
77
  # Test the number against negative infinity
80
78
  #
@@ -86,31 +84,16 @@ module Axiom
86
84
  # returned if the other object is not negative infinity
87
85
  #
88
86
  # @api private
89
- def self.<=>(_other)
87
+ def <=>(_other)
90
88
  comparison = super
91
89
  -comparison if comparison
92
90
  end
93
91
 
94
- # The inverse of negative infinity
95
- #
96
- # @return [Class<Infinity>]
97
- #
98
- # @api private
99
- def self.inverse
100
- Infinity
101
- end
102
- private_class_method :inverse
92
+ end # class NegativeInfinity
103
93
 
104
- # The numeric representation of negative infinity
105
- #
106
- # @return [Float]
107
- #
108
- # @api private
109
- def self.number
110
- -::Float::INFINITY
111
- end
112
- private_class_method :number
94
+ # Define inverse classes
95
+ Infinity.inverse NegativeInfinity
96
+ NegativeInfinity.inverse Infinity
113
97
 
114
- end # class NegativeInfinity
115
98
  end # module Types
116
99
  end # module Axiom
@@ -105,7 +105,7 @@ module Axiom
105
105
  # @api private
106
106
  def assert_method_available(name)
107
107
  return unless respond_to?(name)
108
- raise(
108
+ fail(
109
109
  ReservedMethodError,
110
110
  "method named `#{name.inspect}` is already defined"
111
111
  )
@@ -131,6 +131,33 @@ module Axiom
131
131
  constraint(&set.method(:include?))
132
132
  end
133
133
 
134
+ # The base type for the type
135
+ #
136
+ # @return [Class<Axiom::Types::Type>]
137
+ #
138
+ # @api public
139
+ def self.base
140
+ base? ? self : superclass.base
141
+ end
142
+
143
+ # Test if the type is a base type
144
+ #
145
+ # @return [Boolean]
146
+ #
147
+ # @api public
148
+ def self.base?
149
+ !anonymous?
150
+ end
151
+
152
+ # Test if the type is anonymous
153
+ #
154
+ # @return [Boolean]
155
+ #
156
+ # @api public
157
+ def self.anonymous?
158
+ name.to_s.empty?
159
+ end
160
+
134
161
  # Add new constraint to existing constraint, if any
135
162
  #
136
163
  # @param [#call] constraint
@@ -6,6 +6,13 @@ module Axiom
6
6
  # Add a minimum and maximum value constraint to a type
7
7
  module ValueComparable
8
8
 
9
+ # The range of allowed values
10
+ #
11
+ # @return [Range]
12
+ #
13
+ # @api public
14
+ attr_reader :range
15
+
9
16
  # Hook called when module is extended
10
17
  #
11
18
  # Add #minimum and #maximum DSL methods to descendant.
@@ -17,9 +24,7 @@ module Axiom
17
24
  # @api private
18
25
  def self.extended(descendant)
19
26
  super
20
- descendant.class_eval do
21
- accept_options :minimum, :maximum
22
- end
27
+ descendant.accept_options :minimum, :maximum
23
28
  end
24
29
 
25
30
  # Finalize by setting up a value range constraint
@@ -29,7 +34,8 @@ module Axiom
29
34
  # @api private
30
35
  def finalize
31
36
  return self if frozen?
32
- has_value_within_range
37
+ @range = IceNine.deep_freeze(minimum..maximum)
38
+ use_value_within_range
33
39
  super
34
40
  end
35
41
 
@@ -42,8 +48,7 @@ module Axiom
42
48
  # @todo freeze the minimum and maximum
43
49
  #
44
50
  # @api private
45
- def has_value_within_range
46
- range = minimum..maximum
51
+ def use_value_within_range
47
52
  constraint(range.method(:cover?))
48
53
  end
49
54
 
@@ -4,7 +4,7 @@ module Axiom
4
4
  module Types
5
5
 
6
6
  # Gem version
7
- VERSION = '0.0.5'.freeze
7
+ VERSION = '0.1.0'.freeze
8
8
 
9
9
  end # module Types
10
10
  end # module Axiom
@@ -11,7 +11,7 @@ describe Axiom::Types, '.finalize' do
11
11
  it_should_behave_like 'a command method'
12
12
 
13
13
  it 'finalizes the descendants' do
14
- descendant.should_receive(:finalize)
14
+ expect(descendant).to receive(:finalize)
15
15
  subject
16
16
  end
17
17
  end
@@ -13,7 +13,7 @@ describe Axiom::Types::Encodable, '.extended' do
13
13
  # RSpec tracks the original method (if any), then we add our own stub that
14
14
  # actually works, and finally when the example finishes RSpec will reset
15
15
  # the Module#extended method back to it's original state.
16
- Module.any_instance.stub(:extended).with(object)
16
+ allow_any_instance_of(Module).to receive(:extended).with(object)
17
17
 
18
18
  delegated_ancestor = false
19
19
  Module.send(:undef_method, :extended)
@@ -9,7 +9,7 @@ describe Axiom::Types::Encodable, '#finalize' do
9
9
 
10
10
  # Test if Symbol encoding is supported
11
11
  let(:symbol_encoding) do
12
- ! RUBY_PLATFORM.include?('java') && begin
12
+ !RUBY_PLATFORM.include?('java') && begin
13
13
  encoding = Encoding::UTF_32BE
14
14
  ''.force_encoding(encoding).to_sym.encoding.equal?(encoding)
15
15
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::Infinity, '.coerce' do
5
+ describe Axiom::Types::Infinity, '#coerce' do
6
6
  subject { object.coerce(other) }
7
7
 
8
- let(:object) { described_class }
8
+ let(:object) { described_class.instance }
9
9
 
10
10
  [
11
11
  1, # Fixnum
@@ -18,7 +18,7 @@ describe Axiom::Types::Infinity, '.coerce' do
18
18
  let(:other) { number }
19
19
 
20
20
  it 'coerces into an array containing inverse and self' do
21
- should eql([Axiom::Types::NegativeInfinity, object])
21
+ should eql([Axiom::Types::NegativeInfinity.instance, object])
22
22
  end
23
23
 
24
24
  it 'coerces when comparing' do
@@ -32,7 +32,7 @@ describe Axiom::Types::Infinity, '.coerce' do
32
32
  let(:other) { Float::INFINITY }
33
33
 
34
34
  it 'coerces into an array containing inverse and self' do
35
- should eql([Axiom::Types::Infinity, object])
35
+ should eql([Axiom::Types::Infinity.instance, object])
36
36
  end
37
37
 
38
38
  it 'coerces when comparing' do
@@ -45,7 +45,7 @@ describe Axiom::Types::Infinity, '.coerce' do
45
45
  let(:other) { -Float::INFINITY }
46
46
 
47
47
  it 'coerces into an array containing inverse and self' do
48
- should eql([Axiom::Types::NegativeInfinity, object])
48
+ should eql([Axiom::Types::NegativeInfinity.instance, object])
49
49
  end
50
50
 
51
51
  it 'coerces when comparing' do
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::Infinity, '.<=>' do
5
+ describe Axiom::Types::Infinity, '#<=>' do
6
6
  subject { object <=> other }
7
7
 
8
- let(:object) { described_class }
8
+ let(:object) { described_class.instance }
9
9
 
10
10
  [
11
11
  1, # Fixnum
@@ -26,7 +26,7 @@ describe Axiom::Types::Infinity, '.<=>' do
26
26
  end
27
27
 
28
28
  context 'when the other object is negative infinity' do
29
- let(:other) { Axiom::Types::NegativeInfinity }
29
+ let(:other) { Axiom::Types::NegativeInfinity.instance }
30
30
 
31
31
  it { should be(1) }
32
32
 
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::Infinity, '.succ' do
5
+ describe Axiom::Types::Infinity, '#succ' do
6
6
  subject { object.succ }
7
7
 
8
- let(:object) { described_class }
8
+ let(:object) { described_class.instance }
9
9
 
10
10
  it { should be(object) }
11
11
  end
@@ -13,7 +13,7 @@ describe Axiom::Types::LengthComparable, '.extended' do
13
13
  # RSpec tracks the original method (if any), then we add our own stub that
14
14
  # actually works, and finally when the example finishes RSpec will reset
15
15
  # the Module#extended method back to it's original state.
16
- Module.any_instance.stub(:extended).with(object)
16
+ allow_any_instance_of(Module).to receive(:extended).with(object)
17
17
 
18
18
  delegated_ancestor = false
19
19
  Module.send(:undef_method, :extended)
@@ -32,10 +32,12 @@ describe Axiom::Types::LengthComparable, '.extended' do
32
32
  end
33
33
 
34
34
  it 'sets the default minimum_length' do
35
- expect(subject.minimum_length).to equal(Axiom::Types::Infinity)
35
+ expect(subject.minimum_length)
36
+ .to equal(Axiom::Types::Infinity.instance)
36
37
  end
37
38
 
38
39
  it 'sets the default maximum_length' do
39
- expect(subject.maximum_length).to equal(Axiom::Types::NegativeInfinity)
40
+ expect(subject.maximum_length)
41
+ .to equal(Axiom::Types::NegativeInfinity.instance)
40
42
  end
41
43
  end
@@ -18,6 +18,7 @@ describe Axiom::Types::LengthComparable, '#finalize' do
18
18
 
19
19
  it { should be_frozen }
20
20
 
21
+ its(:range) { should be_frozen }
21
22
  its(:constraint) { should be_frozen }
22
23
 
23
24
  it 'adds a constraint that returns true for a length within range' do
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::LengthComparable, '#range' do
6
+ subject { object.range }
7
+
8
+ let(:object) do
9
+ Class.new(Axiom::Types::Type) do
10
+ extend Axiom::Types::LengthComparable
11
+ minimum_length 1
12
+ maximum_length 2
13
+ end
14
+ end
15
+
16
+ before do
17
+ object.finalize
18
+ end
19
+
20
+ it_should_behave_like 'an idempotent method'
21
+
22
+ it { should be_frozen }
23
+
24
+ it { should eql(1..2) }
25
+ end
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Axiom::Types::NegativeInfinity, '.<=>' do
5
+ describe Axiom::Types::NegativeInfinity, '#<=>' do
6
6
  subject { object <=> other }
7
7
 
8
- let(:object) { described_class }
8
+ let(:object) { described_class.instance }
9
9
 
10
10
  [
11
11
  1, # Fixnum
@@ -26,7 +26,7 @@ describe Axiom::Types::NegativeInfinity, '.<=>' do
26
26
  end
27
27
 
28
28
  context 'when the other object is infinity' do
29
- let(:other) { Axiom::Types::Infinity }
29
+ let(:other) { Axiom::Types::Infinity.instance }
30
30
 
31
31
  it { should be(-1) }
32
32
 
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Object, '.inspect' do
6
+ subject { object.inspect }
7
+
8
+ let(:object) { described_class }
9
+
10
+ it { should eql("Axiom::Types::Object (#{object.primitive})") }
11
+ end
@@ -22,7 +22,7 @@ describe Axiom::Types::Options, '#inherited' do
22
22
  end
23
23
 
24
24
  it 'delegates to the ancestor' do
25
- ancestor.should_receive(:inherited).twice
25
+ expect(ancestor).to receive(:inherited).twice
26
26
  subject
27
27
  end
28
28
 
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Type, '.anonymous?' do
6
+ subject { object.anonymous? }
7
+
8
+ context 'when the type is named' do
9
+ let(:object) { described_class }
10
+
11
+ it { should be(false) }
12
+ end
13
+
14
+ context 'when the type is anonymous' do
15
+ let(:object) { Class.new(described_class) }
16
+
17
+ it { should be(true) }
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Type, '.base?' do
6
+ subject { object.base? }
7
+
8
+ context 'when the type is named' do
9
+ let(:object) { described_class }
10
+
11
+ it { should be(true) }
12
+ end
13
+
14
+ context 'when the type is anonymous' do
15
+ let(:object) { Class.new(described_class) }
16
+
17
+ it { should be(false) }
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::Type, '.base' do
6
+ subject { object.base }
7
+
8
+ context 'when the type is named' do
9
+ let(:object) { described_class }
10
+
11
+ it { should be(object) }
12
+ end
13
+
14
+ context 'when the type is anonymous' do
15
+ let(:object) { Class.new(Class.new(described_class)) }
16
+
17
+ it { should be(described_class) }
18
+ end
19
+ end
@@ -26,8 +26,8 @@ describe Axiom::Types::Type, '.includes' do
26
26
  end
27
27
 
28
28
  it 'removes duplicate members' do
29
- member.should_receive(:frozen?).and_return(true)
30
- member.should_receive(:hash).exactly(3).times.and_return(1)
29
+ expect(member).to receive(:freeze).and_return(member)
30
+ expect(member).to receive(:hash).exactly(3).times.and_return(1)
31
31
  subject
32
32
  expect(object).to include(member)
33
33
  end
@@ -13,7 +13,7 @@ describe Axiom::Types::ValueComparable, '.extended' do
13
13
  # RSpec tracks the original method (if any), then we add our own stub that
14
14
  # actually works, and finally when the example finishes RSpec will reset
15
15
  # the Module#extended method back to it's original state.
16
- Module.any_instance.stub(:extended).with(object)
16
+ allow_any_instance_of(Module).to receive(:extended).with(object)
17
17
 
18
18
  delegated_ancestor = false
19
19
  Module.send(:undef_method, :extended)
@@ -18,6 +18,7 @@ describe Axiom::Types::ValueComparable, '#finalize' do
18
18
 
19
19
  it { should be_frozen }
20
20
 
21
+ its(:range) { should be_frozen }
21
22
  its(:constraint) { should be_frozen }
22
23
 
23
24
  it 'adds a constraint that returns true for a value within range' do
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Axiom::Types::ValueComparable, '#range' do
6
+ subject { object.range }
7
+
8
+ let(:object) do
9
+ Class.new(Axiom::Types::Type) do
10
+ extend Axiom::Types::ValueComparable
11
+ minimum 1
12
+ maximum 2
13
+ end
14
+ end
15
+
16
+ before do
17
+ object.finalize
18
+ end
19
+
20
+ it_should_behave_like 'an idempotent method'
21
+
22
+ it { should be_frozen }
23
+
24
+ it { should eql(1..2) }
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: axiom-types
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Kubb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-06 00:00:00.000000000 Z
11
+ date: 2014-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: descendants_tracker
@@ -16,48 +16,62 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.1
19
+ version: 0.0.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.1
26
+ version: 0.0.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ice_nine
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: '0.9'
33
+ version: 0.11.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: '0.9'
40
+ version: 0.11.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: thread_safe
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.3
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.3
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ~>
46
60
  - !ruby/object:Gem::Version
47
- version: '1.3'
48
- - - ! '>='
61
+ version: '1.5'
62
+ - - '>='
49
63
  - !ruby/object:Gem::Version
50
- version: 1.3.5
64
+ version: 1.5.2
51
65
  type: :development
52
66
  prerelease: false
53
67
  version_requirements: !ruby/object:Gem::Requirement
54
68
  requirements:
55
69
  - - ~>
56
70
  - !ruby/object:Gem::Version
57
- version: '1.3'
58
- - - ! '>='
71
+ version: '1.5'
72
+ - - '>='
59
73
  - !ruby/object:Gem::Version
60
- version: 1.3.5
74
+ version: 1.5.2
61
75
  description: Abstract types for logic programming
62
76
  email: dan.kubb@gmail.com
63
77
  executables: []
@@ -70,6 +84,7 @@ extra_rdoc_files:
70
84
  files:
71
85
  - .gitignore
72
86
  - .rspec
87
+ - .rubocop.yml
73
88
  - .ruby-gemset
74
89
  - .travis.yml
75
90
  - .yardopts
@@ -126,19 +141,24 @@ files:
126
141
  - spec/unit/axiom/types/encodable/finalize_spec.rb
127
142
  - spec/unit/axiom/types/hash/class_methods/finalize_spec.rb
128
143
  - spec/unit/axiom/types/hash/class_methods/infer_spec.rb
129
- - spec/unit/axiom/types/infinity/class_methods/coerce_spec.rb
130
- - spec/unit/axiom/types/infinity/class_methods/spaceship_operator_spec.rb
131
- - spec/unit/axiom/types/infinity/class_methods/succ_spec.rb
144
+ - spec/unit/axiom/types/infinity/coerce_spec.rb
145
+ - spec/unit/axiom/types/infinity/spaceship_operator_spec.rb
146
+ - spec/unit/axiom/types/infinity/succ_spec.rb
132
147
  - spec/unit/axiom/types/length_comparable/class_methods/extended_spec.rb
133
148
  - spec/unit/axiom/types/length_comparable/finalize_spec.rb
134
- - spec/unit/axiom/types/negative_infinity/class_methods/spaceship_operator_spec.rb
149
+ - spec/unit/axiom/types/length_comparable/range_spec.rb
150
+ - spec/unit/axiom/types/negative_infinity/spaceship_operator_spec.rb
135
151
  - spec/unit/axiom/types/object/class_methods/coercion_method_spec.rb
136
152
  - spec/unit/axiom/types/object/class_methods/finalize_spec.rb
137
153
  - spec/unit/axiom/types/object/class_methods/infer_spec.rb
154
+ - spec/unit/axiom/types/object/class_methods/inspect_spec.rb
138
155
  - spec/unit/axiom/types/object/class_methods/primitive_spec.rb
139
156
  - spec/unit/axiom/types/options/accept_options_spec.rb
140
157
  - spec/unit/axiom/types/options/inherited_spec.rb
141
158
  - spec/unit/axiom/types/set/class_methods/infer_spec.rb
159
+ - spec/unit/axiom/types/type/class_methods/anonymous_predicate_spec.rb
160
+ - spec/unit/axiom/types/type/class_methods/base_predicate_spec.rb
161
+ - spec/unit/axiom/types/type/class_methods/base_spec.rb
142
162
  - spec/unit/axiom/types/type/class_methods/constraint_spec.rb
143
163
  - spec/unit/axiom/types/type/class_methods/finalize_spec.rb
144
164
  - spec/unit/axiom/types/type/class_methods/include_predicate_spec.rb
@@ -147,6 +167,7 @@ files:
147
167
  - spec/unit/axiom/types/type/class_methods/new_spec.rb
148
168
  - spec/unit/axiom/types/value_comparable/class_methods/extended_spec.rb
149
169
  - spec/unit/axiom/types/value_comparable/finalize_spec.rb
170
+ - spec/unit/axiom/types/value_comparable/range_spec.rb
150
171
  homepage: https://github.com/dkubb/axiom-types
151
172
  licenses:
152
173
  - MIT
@@ -157,17 +178,17 @@ require_paths:
157
178
  - lib
158
179
  required_ruby_version: !ruby/object:Gem::Requirement
159
180
  requirements:
160
- - - ! '>='
181
+ - - '>='
161
182
  - !ruby/object:Gem::Version
162
- version: '0'
183
+ version: 1.9.3
163
184
  required_rubygems_version: !ruby/object:Gem::Requirement
164
185
  requirements:
165
- - - ! '>='
186
+ - - '>='
166
187
  - !ruby/object:Gem::Version
167
188
  version: '0'
168
189
  requirements: []
169
190
  rubyforge_project:
170
- rubygems_version: 2.1.1
191
+ rubygems_version: 2.1.11
171
192
  signing_key:
172
193
  specification_version: 4
173
194
  summary: Define types with optional constraints for use within axiom and other libraries.
@@ -182,19 +203,24 @@ test_files:
182
203
  - spec/unit/axiom/types/encodable/finalize_spec.rb
183
204
  - spec/unit/axiom/types/hash/class_methods/finalize_spec.rb
184
205
  - spec/unit/axiom/types/hash/class_methods/infer_spec.rb
185
- - spec/unit/axiom/types/infinity/class_methods/coerce_spec.rb
186
- - spec/unit/axiom/types/infinity/class_methods/spaceship_operator_spec.rb
187
- - spec/unit/axiom/types/infinity/class_methods/succ_spec.rb
206
+ - spec/unit/axiom/types/infinity/coerce_spec.rb
207
+ - spec/unit/axiom/types/infinity/spaceship_operator_spec.rb
208
+ - spec/unit/axiom/types/infinity/succ_spec.rb
188
209
  - spec/unit/axiom/types/length_comparable/class_methods/extended_spec.rb
189
210
  - spec/unit/axiom/types/length_comparable/finalize_spec.rb
190
- - spec/unit/axiom/types/negative_infinity/class_methods/spaceship_operator_spec.rb
211
+ - spec/unit/axiom/types/length_comparable/range_spec.rb
212
+ - spec/unit/axiom/types/negative_infinity/spaceship_operator_spec.rb
191
213
  - spec/unit/axiom/types/object/class_methods/coercion_method_spec.rb
192
214
  - spec/unit/axiom/types/object/class_methods/finalize_spec.rb
193
215
  - spec/unit/axiom/types/object/class_methods/infer_spec.rb
216
+ - spec/unit/axiom/types/object/class_methods/inspect_spec.rb
194
217
  - spec/unit/axiom/types/object/class_methods/primitive_spec.rb
195
218
  - spec/unit/axiom/types/options/accept_options_spec.rb
196
219
  - spec/unit/axiom/types/options/inherited_spec.rb
197
220
  - spec/unit/axiom/types/set/class_methods/infer_spec.rb
221
+ - spec/unit/axiom/types/type/class_methods/anonymous_predicate_spec.rb
222
+ - spec/unit/axiom/types/type/class_methods/base_predicate_spec.rb
223
+ - spec/unit/axiom/types/type/class_methods/base_spec.rb
198
224
  - spec/unit/axiom/types/type/class_methods/constraint_spec.rb
199
225
  - spec/unit/axiom/types/type/class_methods/finalize_spec.rb
200
226
  - spec/unit/axiom/types/type/class_methods/include_predicate_spec.rb
@@ -203,4 +229,5 @@ test_files:
203
229
  - spec/unit/axiom/types/type/class_methods/new_spec.rb
204
230
  - spec/unit/axiom/types/value_comparable/class_methods/extended_spec.rb
205
231
  - spec/unit/axiom/types/value_comparable/finalize_spec.rb
232
+ - spec/unit/axiom/types/value_comparable/range_spec.rb
206
233
  has_rdoc: