myrrha 1.2.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|