boundy 0.3.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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/lib/boundy.rb +19 -0
  3. data/lib/boundy/bound.rb +65 -0
  4. data/lib/boundy/bound/comparator.rb +67 -0
  5. data/lib/boundy/bound/constrainer.rb +29 -0
  6. data/lib/boundy/bound/infinite.rb +46 -0
  7. data/lib/boundy/bound/infinite/above.rb +12 -0
  8. data/lib/boundy/bound/infinite/below.rb +13 -0
  9. data/lib/boundy/comparator.rb +19 -0
  10. data/lib/boundy/comparators.rb +28 -0
  11. data/lib/boundy/domain.rb +115 -0
  12. data/lib/boundy/domain/anterior.rb +45 -0
  13. data/lib/boundy/domain/builder.rb +31 -0
  14. data/lib/boundy/domain/comparator.rb +26 -0
  15. data/lib/boundy/domain/constrainer.rb +21 -0
  16. data/lib/boundy/domain/finite.rb +64 -0
  17. data/lib/boundy/domain/posterior.rb +43 -0
  18. data/lib/boundy/formatter.rb +9 -0
  19. data/lib/boundy/formatter/sql.rb +26 -0
  20. data/lib/boundy/formatter/sql/domain.rb +20 -0
  21. data/lib/boundy/formatter/sql/domain/plugin.rb +22 -0
  22. data/lib/boundy/formatter/sql/factory.rb +14 -0
  23. data/lib/boundy/formatter/sql/plugin.rb +38 -0
  24. data/lib/boundy/formatters/bound.rb +16 -0
  25. data/lib/boundy/formatters/domain.rb +12 -0
  26. data/lib/boundy/formatters/fixnum.rb +20 -0
  27. data/lib/boundy/formatters/sql/bound.rb +22 -0
  28. data/lib/boundy/formatters/sql/domain.rb +28 -0
  29. data/lib/boundy/formatters/sql/domain/anterior.rb +23 -0
  30. data/lib/boundy/formatters/sql/domain/finite.rb +24 -0
  31. data/lib/boundy/formatters/sql/domain/posterior.rb +23 -0
  32. data/lib/boundy/formatters/time.rb +42 -0
  33. data/lib/boundy/range/comparator.rb +38 -0
  34. data/lib/boundy/range/constrainer.rb +17 -0
  35. data/lib/boundy/time/comparator.rb +37 -0
  36. data/test/integration/boundy_test.rb +37 -0
  37. data/test/integration/domain_test.rb +18 -0
  38. data/test/integration/formatter/sql_test.rb +21 -0
  39. data/test/integration/test_helper.rb +14 -0
  40. data/test/unit/boundy/bound/comparator_test.rb +37 -0
  41. data/test/unit/boundy/bound/constrainer_test.rb +123 -0
  42. data/test/unit/boundy/bound/infinite/above_test.rb +36 -0
  43. data/test/unit/boundy/bound/infinite/below_test.rb +36 -0
  44. data/test/unit/boundy/bound/infinite_test.rb +0 -0
  45. data/test/unit/boundy/bound_test.rb +86 -0
  46. data/test/unit/boundy/comparator_test.rb +0 -0
  47. data/test/unit/boundy/domain/anterior_test.rb +103 -0
  48. data/test/unit/boundy/domain/comparator_test.rb +75 -0
  49. data/test/unit/boundy/domain/constrainer_test.rb +11 -0
  50. data/test/unit/boundy/domain/posterior_test.rb +75 -0
  51. data/test/unit/boundy/domain_test.rb +50 -0
  52. data/test/unit/boundy/formatter/sql/domain/plugin_test.rb +16 -0
  53. data/test/unit/boundy/formatter/sql/plugin_test.rb +50 -0
  54. data/test/unit/boundy/formatter/sql_test.rb +26 -0
  55. data/test/unit/boundy/formatters/bound_test.rb +43 -0
  56. data/test/unit/boundy/formatters/domain_test.rb +12 -0
  57. data/test/unit/boundy/formatters/sql/domain/anterior_test.rb +29 -0
  58. data/test/unit/boundy/formatters/sql/domain/finite_test.rb +35 -0
  59. data/test/unit/boundy/formatters/sql/domain/posterior_test.rb +30 -0
  60. data/test/unit/boundy/formatters/time_test.rb +27 -0
  61. data/test/unit/boundy/range/comparator_test.rb +44 -0
  62. data/test/unit/boundy/range/constrainer_test.rb +11 -0
  63. data/test/unit/boundy/time/comparator_test.rb +40 -0
  64. data/test/unit/test_helper.rb +14 -0
  65. metadata +154 -0
@@ -0,0 +1,31 @@
1
+ module Boundy
2
+ module Domain
3
+ module Builder
4
+ def self.builders
5
+ [
6
+ {
7
+ bounds: {
8
+ from: Boundy::Bound::Infinite::Below,
9
+ to: Boundy::Bound
10
+ },
11
+ builder: Proc.new {|b,e| Boundy::Domain::Anterior.new(e) }
12
+ },
13
+ {
14
+ bounds: {
15
+ from: Boundy::Bound,
16
+ to: Boundy::Bound
17
+ },
18
+ builder: Proc.new {|b,e| Boundy::Domain::Finite.new(b,e) }
19
+ },
20
+ {
21
+ bounds: {
22
+ from: Boundy::Bound,
23
+ to: Boundy::Bound::Infinite::Above
24
+ },
25
+ builder: Proc.new {|b,e| Boundy::Domain::Posterior.new(b) }
26
+ }
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ require 'boundy/comparator'
2
+
3
+ module Boundy
4
+ module Domain
5
+ class Comparator
6
+ include Boundy::Comparator
7
+
8
+ def initialize(datum, subject)
9
+ @datum = datum
10
+ @subject = subject
11
+ end
12
+
13
+ def after?
14
+ @subject.from > @datum && @subject.to >= @datum
15
+ end
16
+
17
+ def before?
18
+ @subject.from <= @datum && @subject.to < @datum
19
+ end
20
+
21
+ def within?
22
+ @subject.from <= @datum && @subject.to >= @datum
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require 'boundy/bound/constrainer'
2
+ require 'boundy/domain'
3
+
4
+ module Boundy
5
+ module Domain
6
+ class Constrainer
7
+ def initialize(me, other)
8
+ @me = me
9
+ @other = other
10
+ end
11
+
12
+
13
+ def constrain
14
+ from = Boundy::Bound::Constrainer.new(@me.from, @other.from)
15
+ to = Boundy::Bound::Constrainer.new(@me.to, @other.to)
16
+
17
+ Boundy::Domain.new(from.max, to.min)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ require 'boundy/domain'
2
+
3
+ module Boundy
4
+ module Domain
5
+ class Finite
6
+ def self.builder
7
+ {
8
+ bounds: {
9
+ from: Boundy::Bound,
10
+ to: Boundy::Bound
11
+ },
12
+ builder: Proc.new {|b,e| self.new(b,e) }
13
+ }
14
+ end
15
+
16
+ include Domain::Plugin
17
+
18
+ def initialize(b,e)
19
+ case b
20
+ when Boundy::Bound
21
+ @from = b
22
+ @to = e
23
+ else
24
+ raise "I can't convert #{b.class.name} into a Boundy::Domain::Finite"
25
+ end
26
+ unless valid?
27
+ raise "Backlooking ranges aren't allowed.\n\nFROM: #{@from.inspect}\nTO: #{@to.inspect}"
28
+ end
29
+ end
30
+
31
+ def valid?
32
+ raise if from.nil?
33
+ raise if to.nil?
34
+ raise if from.class < Boundy::Bound::Infinite
35
+ raise if to.class < Boundy::Bound::Infinite
36
+
37
+ from <= to
38
+ end
39
+
40
+
41
+ def strictly_earlier?(subject)
42
+ @from.before?(subject)
43
+ end
44
+
45
+ def strictly_after?(subject)
46
+ @to.after?(subject)
47
+ end
48
+
49
+ def partially_after?(subject)
50
+ @from.after?(subject) && @to.within?(subject)
51
+ end
52
+
53
+ def partially_before?(subject)
54
+ @from.within?(subject) && @to.before?(subject)
55
+ end
56
+
57
+ def partially_within?(subject)
58
+ [:within?, :partially_before?, :partially_after?].any? do |m|
59
+ send(m, subject)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ require 'boundy/domain'
2
+ require 'boundy/bound'
3
+ require 'boundy/bound/infinite/below'
4
+
5
+ module Boundy
6
+ module Domain
7
+ class Posterior
8
+ def self.builder
9
+ {
10
+ bounds: {
11
+ from: Boundy::Bound::Infinite::Below,
12
+ to: Boundy::Bound
13
+ },
14
+ builder: Proc.new {|b,e| self.new(e)}
15
+ }
16
+ end
17
+
18
+ include Domain::Plugin
19
+
20
+ def initialize(datum)
21
+ if datum.nil?
22
+ raise
23
+ end
24
+
25
+ @from = Boundy::Bound::Infinite::Below.new
26
+ @to = case datum
27
+ when Boundy::Bound
28
+ datum
29
+ else
30
+ Boundy::Bound.new(datum)
31
+ end
32
+ end
33
+
34
+ def cute
35
+ "[-infinity, #{@to.datum}]"
36
+ end
37
+
38
+ def inspect
39
+ "#<#{self.class.name} bounded above by #{@to.inspect}>"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ module Boundy
2
+ module Formatter
3
+ def sql
4
+ Boundy::Formatter::Sql
5
+ end
6
+ end
7
+ end
8
+
9
+
@@ -0,0 +1,26 @@
1
+ require 'boundy'
2
+ require 'boundy/formatter/sql/plugin'
3
+
4
+ require 'punchout'
5
+
6
+ require 'boundy/formatter/sql/factory'
7
+
8
+ module Boundy
9
+ module Formatter
10
+ class Sql
11
+ def initialize(obj, name)
12
+ formatter_factory = Plugin.for(obj)
13
+ if formatter_factory.nil?
14
+ raise "No formatter registered for #{obj.class}: #{obj.inspect}"
15
+ end
16
+ @formatter = formatter_factory.build(obj, name)
17
+ end
18
+
19
+ def to_s
20
+ @formatter.to_s
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'boundy/formatters/sql/domain'
@@ -0,0 +1,20 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+
3
+ module Boundy
4
+ module Formatter
5
+ class Sql
6
+ class Domain
7
+ def initialize(obj, name)
8
+ @formatter = Plugin.for(obj).new(obj,name)
9
+ if @formatter.nil?
10
+ raise "No formatter registered for #{obj.inspect}"
11
+ end
12
+ end
13
+
14
+ def to_s
15
+ @formatter.to_s
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Boundy
2
+ module Formatter
3
+ class Sql
4
+ class Domain
5
+ module Plugin
6
+ extend Punchout::Punchable
7
+ class << self
8
+ def included(base)
9
+ Boundy.logger.info "REGISTERING #{base} AS DOMAIN FORMATTER FOR #{base.type}"
10
+ matchable = Punchout::Matcher::Ancestry.new(base.type).punches(base)
11
+ puncher.add(matchable)
12
+ end
13
+
14
+ def for(obj)
15
+ punch(obj)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Boundy
2
+ module Formatter
3
+ class Sql
4
+ class Factory
5
+ def initialize(klass)
6
+ @klass = klass
7
+ end
8
+ def build(obj, name)
9
+ @klass.new(obj, name)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require 'boundy'
2
+
3
+ require 'punchout'
4
+ require 'boundy/formatter/sql/factory'
5
+
6
+ module Boundy
7
+ module Formatter
8
+ class Sql
9
+ module Plugin
10
+ extend Punchout::Punchable
11
+ class << self
12
+
13
+ module FactoryMethods
14
+ def factory
15
+ @factory ||= Factory.new(self)
16
+ end
17
+ end
18
+
19
+ def included(base)
20
+ # XXX: This should really become an explicit include.
21
+ unless base.respond_to?(:factory)
22
+ base.instance_exec do
23
+ extend FactoryMethods
24
+ end
25
+ end
26
+ Boundy.logger.info "REGISTERING #{base} AS FORMATTER FOR #{base.type}"
27
+ matchable = Punchout::Matcher::Ancestry.new(base.type).punches(base.factory)
28
+ puncher.add(matchable)
29
+ end
30
+
31
+ def for(obj)
32
+ punch(obj)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ require 'punchout'
2
+ require 'punchout/matcher/ancestry'
3
+
4
+ module Boundy
5
+ module Formatters
6
+ module Bound
7
+ def initialize(bound)
8
+ @bound = bound
9
+ end
10
+
11
+ def to_s
12
+ @formatter.to_s
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ require 'boundy/formatters/bound'
2
+
3
+ module Boundy
4
+ module Formatters
5
+ module Domain
6
+ def initialize(domain)
7
+ @from = domain.from
8
+ @to = domain.to
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Boundy
2
+ module Formatters
3
+ class Fixnum
4
+ def initialize(num, name)
5
+ @num = num
6
+ end
7
+
8
+ def self.type
9
+ ::Fixnum
10
+ end
11
+
12
+ include Boundy::Formatters::Bound
13
+ include Boundy::Formatter::Sql::Plugin
14
+
15
+ def to_s
16
+ @num
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'boundy/bound'
2
+
3
+ require 'boundy/formatter/sql/plugin'
4
+
5
+ require 'boundy/formatters/bound'
6
+
7
+ module Boundy::Formatters::Sql
8
+ class Bound
9
+ def self.type
10
+ Boundy::Bound
11
+ end
12
+
13
+ include Boundy::Formatters::Bound
14
+ include Boundy::Formatter::Sql::Plugin
15
+
16
+ def initialize(bound, name)
17
+ @formatter = Boundy::Formatter::Sql.new(bound.datum, name)
18
+ super(bound)
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,28 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+
3
+ require 'boundy/formatters/domain'
4
+
5
+ module Boundy::Formatters::Sql
6
+ class Domain
7
+ def self.type
8
+ Boundy::Domain::Plugin
9
+ end
10
+
11
+ def initialize(domain, name)
12
+ @formatter = Boundy::Formatter::Sql::Domain::Plugin.for(domain).new(domain,name)
13
+ if @formatter.nil?
14
+ raise "No formatter registered for #{obj.inspect}"
15
+ end
16
+ end
17
+
18
+ include Boundy::Formatter::Sql::Plugin
19
+
20
+ def to_s
21
+ @formatter.to_s
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'boundy/formatters/sql/domain/anterior'
27
+ require 'boundy/formatters/sql/domain/finite'
28
+ require 'boundy/formatters/sql/domain/posterior'
@@ -0,0 +1,23 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+ require 'boundy/domain/anterior'
3
+
4
+ module Boundy::Formatters::Sql
5
+ class Domain
6
+ class Anterior
7
+ def self.type
8
+ Boundy::Domain::Anterior
9
+ end
10
+
11
+ include Boundy::Formatter::Sql::Domain::Plugin
12
+
13
+ def initialize(domain, name)
14
+ @name = name
15
+ @formatter = Boundy::Formatter::Sql.new(domain.from, name)
16
+ end
17
+
18
+ def to_s
19
+ "#{@name} >= '#{@formatter.to_s}'"
20
+ end
21
+ end
22
+ end
23
+ end