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.
- checksums.yaml +7 -0
- data/lib/boundy.rb +19 -0
- data/lib/boundy/bound.rb +65 -0
- data/lib/boundy/bound/comparator.rb +67 -0
- data/lib/boundy/bound/constrainer.rb +29 -0
- data/lib/boundy/bound/infinite.rb +46 -0
- data/lib/boundy/bound/infinite/above.rb +12 -0
- data/lib/boundy/bound/infinite/below.rb +13 -0
- data/lib/boundy/comparator.rb +19 -0
- data/lib/boundy/comparators.rb +28 -0
- data/lib/boundy/domain.rb +115 -0
- data/lib/boundy/domain/anterior.rb +45 -0
- data/lib/boundy/domain/builder.rb +31 -0
- data/lib/boundy/domain/comparator.rb +26 -0
- data/lib/boundy/domain/constrainer.rb +21 -0
- data/lib/boundy/domain/finite.rb +64 -0
- data/lib/boundy/domain/posterior.rb +43 -0
- data/lib/boundy/formatter.rb +9 -0
- data/lib/boundy/formatter/sql.rb +26 -0
- data/lib/boundy/formatter/sql/domain.rb +20 -0
- data/lib/boundy/formatter/sql/domain/plugin.rb +22 -0
- data/lib/boundy/formatter/sql/factory.rb +14 -0
- data/lib/boundy/formatter/sql/plugin.rb +38 -0
- data/lib/boundy/formatters/bound.rb +16 -0
- data/lib/boundy/formatters/domain.rb +12 -0
- data/lib/boundy/formatters/fixnum.rb +20 -0
- data/lib/boundy/formatters/sql/bound.rb +22 -0
- data/lib/boundy/formatters/sql/domain.rb +28 -0
- data/lib/boundy/formatters/sql/domain/anterior.rb +23 -0
- data/lib/boundy/formatters/sql/domain/finite.rb +24 -0
- data/lib/boundy/formatters/sql/domain/posterior.rb +23 -0
- data/lib/boundy/formatters/time.rb +42 -0
- data/lib/boundy/range/comparator.rb +38 -0
- data/lib/boundy/range/constrainer.rb +17 -0
- data/lib/boundy/time/comparator.rb +37 -0
- data/test/integration/boundy_test.rb +37 -0
- data/test/integration/domain_test.rb +18 -0
- data/test/integration/formatter/sql_test.rb +21 -0
- data/test/integration/test_helper.rb +14 -0
- data/test/unit/boundy/bound/comparator_test.rb +37 -0
- data/test/unit/boundy/bound/constrainer_test.rb +123 -0
- data/test/unit/boundy/bound/infinite/above_test.rb +36 -0
- data/test/unit/boundy/bound/infinite/below_test.rb +36 -0
- data/test/unit/boundy/bound/infinite_test.rb +0 -0
- data/test/unit/boundy/bound_test.rb +86 -0
- data/test/unit/boundy/comparator_test.rb +0 -0
- data/test/unit/boundy/domain/anterior_test.rb +103 -0
- data/test/unit/boundy/domain/comparator_test.rb +75 -0
- data/test/unit/boundy/domain/constrainer_test.rb +11 -0
- data/test/unit/boundy/domain/posterior_test.rb +75 -0
- data/test/unit/boundy/domain_test.rb +50 -0
- data/test/unit/boundy/formatter/sql/domain/plugin_test.rb +16 -0
- data/test/unit/boundy/formatter/sql/plugin_test.rb +50 -0
- data/test/unit/boundy/formatter/sql_test.rb +26 -0
- data/test/unit/boundy/formatters/bound_test.rb +43 -0
- data/test/unit/boundy/formatters/domain_test.rb +12 -0
- data/test/unit/boundy/formatters/sql/domain/anterior_test.rb +29 -0
- data/test/unit/boundy/formatters/sql/domain/finite_test.rb +35 -0
- data/test/unit/boundy/formatters/sql/domain/posterior_test.rb +30 -0
- data/test/unit/boundy/formatters/time_test.rb +27 -0
- data/test/unit/boundy/range/comparator_test.rb +44 -0
- data/test/unit/boundy/range/constrainer_test.rb +11 -0
- data/test/unit/boundy/time/comparator_test.rb +40 -0
- data/test/unit/test_helper.rb +14 -0
- 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,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,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,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
|