myrrha 1.2.2 → 2.0.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.
- data/CHANGELOG.md +62 -29
- data/README.md +117 -121
- data/Rakefile +0 -12
- data/examples/sbyc_domain.rb +1 -1
- data/lib/myrrha.rb +11 -364
- data/lib/myrrha/coerce.rb +22 -25
- data/lib/myrrha/coercions.rb +265 -0
- data/lib/myrrha/domain.rb +18 -0
- data/lib/myrrha/domain/coercion_methods.rb +17 -0
- data/lib/myrrha/domain/impl.rb +50 -0
- data/lib/myrrha/domain/sbyc.rb +78 -0
- data/lib/myrrha/domain/value_methods.rb +60 -0
- data/lib/myrrha/errors.rb +12 -0
- data/lib/myrrha/loader.rb +0 -1
- data/lib/myrrha/to_ruby_literal.rb +1 -1
- data/lib/myrrha/version.rb +3 -3
- data/myrrha.noespec +3 -3
- data/spec/coercions/test_append.rb +3 -3
- data/spec/coercions/test_belongs_to.rb +12 -6
- data/spec/coercions/test_convert.rb +5 -5
- data/spec/coercions/test_delegate.rb +35 -0
- data/spec/coercions/test_subdomain.rb +9 -3
- data/spec/domain/impl/test_behavior.rb +41 -0
- data/spec/domain/impl/test_value_methods.rb +101 -0
- data/spec/domain/sbyc/test_behavior.rb +46 -0
- data/spec/domain/test_sbyc.rb +81 -0
- data/spec/myrrha/test_coercions.rb +1 -1
- data/spec/test_myrrha.rb +0 -3
- data/tasks/examples.rake +2 -1
- data/tasks/gem.rake +9 -4
- metadata +83 -43
- data/spec/myrrha/test_domain.rb +0 -116
data/lib/myrrha/loader.rb
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
|
data/lib/myrrha/version.rb
CHANGED
data/myrrha.noespec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
template-info:
|
2
|
-
name:
|
3
|
-
version: 1.7.
|
2
|
+
name: rubygem.noe
|
3
|
+
version: 1.7.4
|
4
4
|
manifest:
|
5
5
|
tasks/debug_mail.txt:
|
6
6
|
safe-override: false
|
@@ -10,7 +10,7 @@ variables:
|
|
10
10
|
upper:
|
11
11
|
Myrrha
|
12
12
|
version:
|
13
|
-
|
13
|
+
2.0.0
|
14
14
|
summary: |-
|
15
15
|
Myrrha provides the coercion framework which is missing to Ruby.
|
16
16
|
description: |-
|
@@ -2,20 +2,26 @@ require 'spec_helper'
|
|
2
2
|
module Myrrha
|
3
3
|
describe "Coercions#belongs_to?" do
|
4
4
|
let(:rules){ Coercions.new }
|
5
|
-
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
class Coercions
|
8
|
+
public :belongs_to?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
specify "with a class" do
|
7
13
|
rules.belongs_to?(12, Integer).should be_true
|
8
14
|
end
|
9
|
-
|
15
|
+
|
10
16
|
specify "with a superclass" do
|
11
17
|
rules.belongs_to?(12, Numeric).should be_true
|
12
18
|
end
|
13
|
-
|
19
|
+
|
14
20
|
specify "with a proc or arity 1" do
|
15
21
|
rules.belongs_to?(12, lambda{|x| x>10}).should be_true
|
16
22
|
rules.belongs_to?(12, lambda{|x| x<10}).should be_false
|
17
23
|
end
|
18
|
-
|
24
|
+
|
19
25
|
specify "with a proc or arity 2" do
|
20
26
|
got = nil
|
21
27
|
l = lambda{|x,t| got = t; t == l }
|
@@ -24,6 +30,6 @@ module Myrrha
|
|
24
30
|
rules.belongs_to?(12, l, :nosuch).should be_false
|
25
31
|
got.should eq(:nosuch)
|
26
32
|
end
|
27
|
-
|
33
|
+
|
28
34
|
end
|
29
|
-
end
|
35
|
+
end
|
@@ -2,16 +2,16 @@ require 'spec_helper'
|
|
2
2
|
module Myrrha
|
3
3
|
describe "Coercions#convert" do
|
4
4
|
let(:graph){ Coercions.new }
|
5
|
-
|
5
|
+
|
6
6
|
subject{ graph.send(:convert, "value", String, converter) }
|
7
|
-
|
7
|
+
|
8
8
|
describe "when passed a proc of arity 2" do
|
9
9
|
let(:converter){ lambda{|v,t| [v,t]} }
|
10
10
|
it{ should eq(["value", String]) }
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
describe "when passed an object that respond to call" do
|
14
|
-
let(:converter){
|
14
|
+
let(:converter){
|
15
15
|
o = Object.new
|
16
16
|
def o.call(arg, t); [arg, t]; end
|
17
17
|
o
|
@@ -20,4 +20,4 @@ module Myrrha
|
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe Coercions, "delegate" do
|
4
|
+
let(:rules){ Coercions.new }
|
5
|
+
|
6
|
+
context 'without block' do
|
7
|
+
before{ rules.delegate(:to_a) }
|
8
|
+
|
9
|
+
it "should delegate if the method exists" do
|
10
|
+
rules.apply([1, 2, 3]).should eq([1, 2, 3])
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should not delegate if the method does not exist" do
|
14
|
+
lambda{
|
15
|
+
rules.apply(self)
|
16
|
+
}.should raise_error(Myrrha::Error)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with a block' do
|
21
|
+
before{ rules.delegate(:to_a){|v,_| v.to_a.reverse} }
|
22
|
+
|
23
|
+
it "should delegate if the method exists" do
|
24
|
+
rules.apply([1, 2, 3]).should eq([3,2,1])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not delegate if the method does not exist" do
|
28
|
+
lambda{
|
29
|
+
rules.apply(self)
|
30
|
+
}.should raise_error(Myrrha::Error)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -2,11 +2,17 @@ require 'spec_helper'
|
|
2
2
|
module Myrrha
|
3
3
|
describe "Coercions#subdomain?" do
|
4
4
|
let(:r){ Coercions.new }
|
5
|
-
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
class Coercions
|
8
|
+
public :subdomain?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
specify {
|
7
13
|
r.subdomain?(Symbol, Object).should be_true
|
8
14
|
r.subdomain?(Class, Module).should be_true
|
9
15
|
}
|
10
|
-
|
16
|
+
|
11
17
|
end
|
12
|
-
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
describe Domain, 'when included' do
|
4
|
+
|
5
|
+
let(:point){
|
6
|
+
Class.new{
|
7
|
+
include Myrrha::Domain::Impl.new([:r, :theta])
|
8
|
+
|
9
|
+
coercions do |c|
|
10
|
+
c.upon(NilClass) {|v,t| new(0.0,0.0) }
|
11
|
+
c.coercion(String) {|v,t| new(*v.split(',').map(&:to_f)) }
|
12
|
+
c.coercion(TrueClass){|v,t| throw :nextrule }
|
13
|
+
c.fallback(TrueClass){|v,t| new(1.0, 1.0) }
|
14
|
+
end
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
let(:origin){ point.new(0.0, 0.0) }
|
19
|
+
let(:oneone){ point.new(1.0, 1.0) }
|
20
|
+
|
21
|
+
it 'installs the domain component names' do
|
22
|
+
point.component_names.should eq([:r, :theta])
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'installs the component readers' do
|
26
|
+
origin.r.should eq(0.0)
|
27
|
+
origin.theta.should eq(0.0)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'has coercions properly installed' do
|
31
|
+
point.coercions.main_target_domain.should eq(point)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'supports expected coercions' do
|
35
|
+
point.coerce(nil).should eq(origin)
|
36
|
+
point.coerce(true).should eq(oneone)
|
37
|
+
point.coerce("2.0,3.0").should eq(point.new(2.0, 3.0))
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
module Domain
|
4
|
+
class Impl
|
5
|
+
describe ValueMethods do
|
6
|
+
|
7
|
+
let(:domain){
|
8
|
+
Class.new{
|
9
|
+
def self.component_names
|
10
|
+
[:a, :b]
|
11
|
+
end
|
12
|
+
include ValueMethods
|
13
|
+
attr_reader :a, :b
|
14
|
+
def initialize(a, b)
|
15
|
+
@a, @b = a, b
|
16
|
+
end
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:object){ domain.new(1, 2) }
|
21
|
+
|
22
|
+
describe "==" do
|
23
|
+
subject{ object == other }
|
24
|
+
|
25
|
+
context 'with itself' do
|
26
|
+
let(:other){ object }
|
27
|
+
it{ should be_true }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with dupped' do
|
31
|
+
let(:other){ object.dup }
|
32
|
+
it{ should be_true }
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with equivalent' do
|
36
|
+
let(:other){ domain.new(1, 2) }
|
37
|
+
it{ should be_true }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with equivalent of a subclass' do
|
41
|
+
let(:other){ Class.new(domain).new(1, 2) }
|
42
|
+
it{ should be_true }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with non equivalent' do
|
46
|
+
let(:other){ domain.new(1, 3) }
|
47
|
+
it{ should be_false }
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with other class' do
|
51
|
+
let(:other){ self }
|
52
|
+
it{ should be_false }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "eql?" do
|
57
|
+
subject{ object.eql?(other) }
|
58
|
+
|
59
|
+
context 'with itself' do
|
60
|
+
let(:other){ object }
|
61
|
+
it{ should be_true }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with dupped' do
|
65
|
+
let(:other){ object.dup }
|
66
|
+
it{ should be_true }
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with equivalent' do
|
70
|
+
let(:other){ domain.new(1, 2) }
|
71
|
+
it{ should be_true }
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with equivalent of a subclass' do
|
75
|
+
let(:other){ Class.new(domain).new(1, 2) }
|
76
|
+
it{ should be_false }
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with non equivalent' do
|
80
|
+
let(:other){ domain.new(1, 3) }
|
81
|
+
it{ should be_false }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with other class' do
|
85
|
+
let(:other){ self }
|
86
|
+
it{ should be_false }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "hash" do
|
91
|
+
subject{ object.hash }
|
92
|
+
|
93
|
+
it 'should be consistent with equal' do
|
94
|
+
subject.should eq(domain.new(1,2).hash)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
module Domain
|
4
|
+
describe SByC, 'when used by extension' do
|
5
|
+
|
6
|
+
class NegInt < Integer
|
7
|
+
extend Myrrha::Domain::SByC.new(Integer, [], lambda{|i| i<0})
|
8
|
+
end
|
9
|
+
|
10
|
+
specify("#name") {
|
11
|
+
NegInt.name.should eq("Myrrha::Domain::NegInt")
|
12
|
+
}
|
13
|
+
|
14
|
+
specify("#new") {
|
15
|
+
NegInt.new(-12).should eq(-12)
|
16
|
+
lambda {
|
17
|
+
NegInt.new(12)
|
18
|
+
}.should raise_error(ArgumentError)
|
19
|
+
}
|
20
|
+
|
21
|
+
specify("#superclass"){
|
22
|
+
NegInt.superclass.should eql(Integer)
|
23
|
+
}
|
24
|
+
|
25
|
+
specify("#superdomain_of?"){
|
26
|
+
NegInt.superdomain_of?(Object).should be_false
|
27
|
+
NegInt.superdomain_of?(Integer).should be_false
|
28
|
+
}
|
29
|
+
|
30
|
+
specify("#coercions"){
|
31
|
+
NegInt.coercions.should be_a(Myrrha::Coercions)
|
32
|
+
NegInt.coercions.main_target_domain.should eq(NegInt)
|
33
|
+
}
|
34
|
+
|
35
|
+
it "should be usable in a case" do
|
36
|
+
[-12, 12].map{|i|
|
37
|
+
case i
|
38
|
+
when NegInt then :negint
|
39
|
+
when Integer then :integer
|
40
|
+
end
|
41
|
+
}.should eq([:negint, :integer])
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Myrrha
|
3
|
+
module Domain
|
4
|
+
describe ".sbyc" do
|
5
|
+
|
6
|
+
specify "the basic contract" do
|
7
|
+
subject = Myrrha::Domain.sbyc{|s| s == 12}
|
8
|
+
subject.should be_a(Class)
|
9
|
+
subject.superclass.should eq(Object)
|
10
|
+
(subject === 12).should be_true
|
11
|
+
(subject === 13).should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
specify "with a ruby superclass" do
|
15
|
+
subject = Myrrha::Domain.sbyc(Integer){|i| i > 0}
|
16
|
+
subject.should be_a(Class)
|
17
|
+
subject.superclass.should eq(Integer)
|
18
|
+
(subject === 12).should be_true
|
19
|
+
(subject === 0).should be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "A factored sub domain of Integer" do
|
23
|
+
PosInt = Myrrha::Domain.sbyc(Integer){|i| i > 0}
|
24
|
+
specify("#name") {
|
25
|
+
PosInt.name.should eq("Myrrha::Domain::PosInt")
|
26
|
+
}
|
27
|
+
specify("#new") {
|
28
|
+
PosInt.new(12).should eq(12)
|
29
|
+
lambda {
|
30
|
+
PosInt.new(0)
|
31
|
+
}.should raise_error(ArgumentError)
|
32
|
+
}
|
33
|
+
specify("#superclass"){
|
34
|
+
PosInt.superclass.should eql(Integer)
|
35
|
+
}
|
36
|
+
specify("#superdomain_of?"){
|
37
|
+
PosInt.superdomain_of?(Object).should be_false
|
38
|
+
PosInt.superdomain_of?(Integer).should be_false
|
39
|
+
}
|
40
|
+
it "should be usable in a case" do
|
41
|
+
[-12, 12].collect{|i|
|
42
|
+
case i
|
43
|
+
when PosInt
|
44
|
+
:posint
|
45
|
+
when Integer
|
46
|
+
:integer
|
47
|
+
end
|
48
|
+
}.should eq([:integer, :posint])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "A factored sub domain of a user-defined Class" do
|
53
|
+
class Color
|
54
|
+
attr_reader :r
|
55
|
+
attr_reader :g
|
56
|
+
attr_reader :b
|
57
|
+
def initialize(r,g,b)
|
58
|
+
raise ArgumentError unless [r,g,b].all?{|i| i.is_a?(Integer)}
|
59
|
+
@r, @g, @b = r, g, b
|
60
|
+
end
|
61
|
+
end
|
62
|
+
RedToZero = Myrrha::Domain.sbyc(Color){|c| c.r == 0}
|
63
|
+
specify("#===") {
|
64
|
+
(RedToZero === Color.new(0,1,1)).should be_true
|
65
|
+
(RedToZero === Color.new(1,1,1)).should be_false
|
66
|
+
}
|
67
|
+
specify("#new") {
|
68
|
+
RedToZero.new(Color.new(0,1,1)).should be_a(Color)
|
69
|
+
RedToZero.new(0, 1, 1).should be_a(Color)
|
70
|
+
lambda{
|
71
|
+
RedToZero.new(Color.new(1,1,1))
|
72
|
+
}.should raise_error(ArgumentError)
|
73
|
+
lambda{
|
74
|
+
RedToZero.new(1, 1, 1)
|
75
|
+
}.should raise_error(ArgumentError)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|