finitio 0.7.0 → 0.8.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 +5 -5
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +40 -41
- data/lib/finitio/generation.rb +106 -0
- data/lib/finitio/generation/ad_type.rb +10 -0
- data/lib/finitio/generation/alias_type.rb +9 -0
- data/lib/finitio/generation/any_type.rb +11 -0
- data/lib/finitio/generation/builtin_type.rb +9 -0
- data/lib/finitio/generation/hash_based_type.rb +15 -0
- data/lib/finitio/generation/heuristic.rb +8 -0
- data/lib/finitio/generation/heuristic/constant.rb +30 -0
- data/lib/finitio/generation/heuristic/random.rb +52 -0
- data/lib/finitio/generation/rel_based_type.rb +13 -0
- data/lib/finitio/generation/seq_type.rb +13 -0
- data/lib/finitio/generation/set_type.rb +13 -0
- data/lib/finitio/generation/sub_type.rb +9 -0
- data/lib/finitio/generation/union_type.rb +10 -0
- data/lib/finitio/inference.rb +51 -0
- data/lib/finitio/support.rb +18 -0
- data/lib/finitio/support/attribute.rb +8 -0
- data/lib/finitio/support/compilation.rb +18 -18
- data/lib/finitio/support/contract.rb +8 -0
- data/lib/finitio/support/fetch_scope.rb +19 -0
- data/lib/finitio/support/heading.rb +36 -1
- data/lib/finitio/syntax.rb +1 -1
- data/lib/finitio/syntax/lexer.citrus +1 -1
- data/lib/finitio/syntax/type.rb +2 -0
- data/lib/finitio/syntax/type/high_order_type_instantiation.rb +29 -0
- data/lib/finitio/syntax/type/high_order_vars.rb +16 -0
- data/lib/finitio/syntax/type/type_def.rb +11 -1
- data/lib/finitio/syntax/types.citrus +14 -1
- data/lib/finitio/system.rb +11 -1
- data/lib/finitio/type.rb +19 -0
- data/lib/finitio/type/ad_type.rb +8 -0
- data/lib/finitio/type/alias_type.rb +8 -0
- data/lib/finitio/type/any_type.rb +12 -0
- data/lib/finitio/type/builtin_type.rb +4 -0
- data/lib/finitio/type/collection_type.rb +15 -0
- data/lib/finitio/type/heading_based_type.rb +17 -0
- data/lib/finitio/type/high_order_type.rb +39 -0
- data/lib/finitio/type/multi_relation_type.rb +4 -0
- data/lib/finitio/type/multi_tuple_type.rb +4 -0
- data/lib/finitio/type/proxy_type.rb +10 -20
- data/lib/finitio/type/relation_type.rb +4 -0
- data/lib/finitio/type/seq_type.rb +1 -1
- data/lib/finitio/type/struct_type.rb +8 -0
- data/lib/finitio/type/sub_type.rb +8 -0
- data/lib/finitio/type/tuple_type.rb +4 -0
- data/lib/finitio/type/union_type.rb +19 -0
- data/lib/finitio/version.rb +1 -1
- data/spec/generation/test_generation.rb +169 -0
- data/spec/heading/test_looks_similar.rb +45 -0
- data/spec/heading/test_suppremum.rb +56 -0
- data/spec/inference/test_inference.rb +42 -0
- data/spec/spec_helper.rb +31 -6
- data/spec/support/test_compare_attrs.rb +67 -0
- data/spec/syntax/test_compile.rb +57 -0
- data/spec/type/ad_type/test_initialize.rb +1 -8
- data/spec/type/relation_type/test_suppremum.rb +104 -0
- data/spec/type/seq_type/test_suppremum.rb +54 -0
- data/spec/type/set_type/test_suppremum.rb +54 -0
- data/spec/type/test_suppremum.rb +49 -0
- data/spec/type/test_unconstrained.rb +150 -0
- data/spec/type/tuple_type/test_suppremum.rb +119 -0
- data/spec/type/union_type/test_suppremum.rb +51 -0
- data/tasks/test.rake +1 -1
- metadata +183 -144
- data/spec/type/proxy_type/test_delegation.rb +0 -37
- data/spec/type/proxy_type/test_resolve.rb +0 -29
data/lib/finitio/type.rb
CHANGED
@@ -54,6 +54,20 @@ module Finitio
|
|
54
54
|
raise NotImplementedError, "Missing #{self.class.name}#dress"
|
55
55
|
end
|
56
56
|
|
57
|
+
def suppremum(other)
|
58
|
+
return self if other == self
|
59
|
+
other._suppremum(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
def _suppremum(other)
|
63
|
+
UnionType.new([other, self])
|
64
|
+
end
|
65
|
+
protected :_suppremum
|
66
|
+
|
67
|
+
def unconstrained
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
57
71
|
def to_s
|
58
72
|
name.to_s
|
59
73
|
end
|
@@ -64,6 +78,10 @@ module Finitio
|
|
64
78
|
}
|
65
79
|
end
|
66
80
|
|
81
|
+
def resolve_proxies(system)
|
82
|
+
raise NotImplementedError, "resolve_proxies must be overriden"
|
83
|
+
end
|
84
|
+
|
67
85
|
protected
|
68
86
|
|
69
87
|
def set_equal?(s1, s2)
|
@@ -94,3 +112,4 @@ require_relative 'type/multi_tuple_type'
|
|
94
112
|
require_relative 'type/relation_type'
|
95
113
|
require_relative 'type/multi_relation_type'
|
96
114
|
require_relative 'type/ad_type'
|
115
|
+
require_relative 'type/high_order_type'
|
data/lib/finitio/type/ad_type.rb
CHANGED
@@ -144,5 +144,13 @@ module Finitio
|
|
144
144
|
end
|
145
145
|
alias :eql? :==
|
146
146
|
|
147
|
+
def resolve_proxies(system)
|
148
|
+
AdType.new(ruby_type, contracts.map{|t| t.resolve_proxies(system)}, name, metadata)
|
149
|
+
end
|
150
|
+
|
151
|
+
def unconstrained
|
152
|
+
AdType.new(ruby_type, contracts.map{|c| c.unconstrained}, name, metadata)
|
153
|
+
end
|
154
|
+
|
147
155
|
end # class AdType
|
148
156
|
end # module Finitio
|
@@ -33,5 +33,13 @@ module Finitio
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def resolve_proxies(system)
|
37
|
+
AliasType.new(target.resolve_proxies(system), name, metadata)
|
38
|
+
end
|
39
|
+
|
40
|
+
def unconstrained
|
41
|
+
AliasType.new(target.unconstrained, name, metadata)
|
42
|
+
end
|
43
|
+
|
36
44
|
end # class AliasType
|
37
45
|
end # module Finitio
|
@@ -38,6 +38,14 @@ module Finitio
|
|
38
38
|
value
|
39
39
|
end
|
40
40
|
|
41
|
+
def suppremum(other)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def _suppremum(other)
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
41
49
|
def ==(other)
|
42
50
|
super || other.is_a?(AnyType)
|
43
51
|
end
|
@@ -47,5 +55,9 @@ module Finitio
|
|
47
55
|
self.class.hash ^ 37
|
48
56
|
end
|
49
57
|
|
58
|
+
def resolve_proxies(system)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
50
62
|
end # class AnyType
|
51
63
|
end # module Finitio
|
@@ -20,5 +20,20 @@ module Finitio
|
|
20
20
|
self.class.hash ^ self.elm_type.hash
|
21
21
|
end
|
22
22
|
|
23
|
+
def suppremum(other)
|
24
|
+
return super unless other.is_a?(CollectionType)
|
25
|
+
return self if other.is_a?(CollectionType) && elm_type == other.elm_type
|
26
|
+
builder = self.class == other.class ? self.class : SeqType
|
27
|
+
builder.new(elm_type.suppremum(other.elm_type))
|
28
|
+
end
|
29
|
+
|
30
|
+
def resolve_proxies(system)
|
31
|
+
self.class.new(elm_type.resolve_proxies(system), name, metadata)
|
32
|
+
end
|
33
|
+
|
34
|
+
def unconstrained
|
35
|
+
self.class.new(elm_type.unconstrained, name, metadata)
|
36
|
+
end
|
37
|
+
|
23
38
|
end # module CollectionType
|
24
39
|
end # module Finitio
|
@@ -15,6 +15,15 @@ module Finitio
|
|
15
15
|
heading.fetch(attrname)
|
16
16
|
end
|
17
17
|
|
18
|
+
def suppremum(other, simple_class, multi_class)
|
19
|
+
return self if self == other
|
20
|
+
return super(other) unless other.is_a?(simple_class) or other.is_a?(multi_class)
|
21
|
+
return super(other) unless heading.looks_similar?(other.heading)
|
22
|
+
result_heading = heading.suppremum(other.heading)
|
23
|
+
builder = result_heading.multi? ? multi_class : simple_class
|
24
|
+
builder.new(result_heading)
|
25
|
+
end
|
26
|
+
|
18
27
|
def ==(other)
|
19
28
|
super || (other.is_a?(self.class) && heading == other.heading)
|
20
29
|
end
|
@@ -24,5 +33,13 @@ module Finitio
|
|
24
33
|
self.class.hash ^ heading.hash
|
25
34
|
end
|
26
35
|
|
36
|
+
def resolve_proxies(system)
|
37
|
+
self.class.new(heading.resolve_proxies(system), name, metadata)
|
38
|
+
end
|
39
|
+
|
40
|
+
def unconstrained
|
41
|
+
self.class.new(heading.unconstrained, name, metadata)
|
42
|
+
end
|
43
|
+
|
27
44
|
end # module HeadingBasedType
|
28
45
|
end # module Finitio
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Finitio
|
2
|
+
class HighOrderType < Type
|
3
|
+
|
4
|
+
def initialize(vars, defn, name = nil, metadata = nil)
|
5
|
+
super(name, metadata)
|
6
|
+
@vars = vars
|
7
|
+
@defn = defn
|
8
|
+
end
|
9
|
+
attr_reader :vars, :defn
|
10
|
+
|
11
|
+
def default_name
|
12
|
+
"Type<#{vars.join(',')}>"
|
13
|
+
end
|
14
|
+
|
15
|
+
def suppremum(other)
|
16
|
+
raise NotImplementedError, "Suppremum is not defined on high order types"
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
super || other.is_a?(HighOrderType) \
|
21
|
+
&& other.vars == self.vars \
|
22
|
+
&& other.defn = self.defn
|
23
|
+
end
|
24
|
+
|
25
|
+
def resolve_proxies(system)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def instantiate(compilation, sub_types)
|
30
|
+
overrides = Hash[vars.zip(sub_types)]
|
31
|
+
defn.resolve_proxies(compilation.with_scope(overrides))
|
32
|
+
end
|
33
|
+
|
34
|
+
def unconstrained
|
35
|
+
HighOrderType.new(vars, defn.unconstrained, name, metadata)
|
36
|
+
end
|
37
|
+
|
38
|
+
end # class HighOrderType
|
39
|
+
end # module Finitio
|
@@ -11,30 +11,20 @@ module Finitio
|
|
11
11
|
end
|
12
12
|
attr_reader :target_name, :target
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
:name,
|
17
|
-
:name=,
|
18
|
-
:default_name,
|
19
|
-
:dress,
|
20
|
-
:undress,
|
21
|
-
:include?,
|
22
|
-
:==,
|
23
|
-
:eql?,
|
24
|
-
:hash,
|
25
|
-
:to_s
|
26
|
-
].each do |meth|
|
27
|
-
define_method(meth) do |*args, &bl|
|
28
|
-
raise Error, "No such type `#{@target_name}` (proxy not resolved?)" unless @target
|
29
|
-
@target.send(meth, *args, &bl)
|
30
|
-
end
|
14
|
+
def default_name
|
15
|
+
"_#{target_name}_"
|
31
16
|
end
|
32
17
|
|
33
|
-
def
|
34
|
-
|
35
|
-
raise Error, "No such type `#{target_name}`"
|
18
|
+
def resolve_proxies(system)
|
19
|
+
system.fetch(target_name){
|
20
|
+
raise Error, "No such type `#{target_name}` in #{system}"
|
36
21
|
}
|
37
22
|
end
|
38
23
|
|
24
|
+
def unconstrained
|
25
|
+
return @target.unconstrained if @target
|
26
|
+
raise Error, "`unconstrained` cannot be call whithout proxies being resolved"
|
27
|
+
end
|
28
|
+
|
39
29
|
end # class ProxyType
|
40
30
|
end # module Finitio
|
@@ -80,5 +80,13 @@ module Finitio
|
|
80
80
|
self.class.hash ^ component_types.hash
|
81
81
|
end
|
82
82
|
|
83
|
+
def resolve_proxies(system)
|
84
|
+
StructType.new(component_types.map{|t| t.resolve_proxies(system)}, name, metadata)
|
85
|
+
end
|
86
|
+
|
87
|
+
def unconstrained
|
88
|
+
StructType.new(component_types.map{|t| t.unconstrained}, name, metadata)
|
89
|
+
end
|
90
|
+
|
83
91
|
end # class StructType
|
84
92
|
end # module Finitio
|
@@ -81,6 +81,10 @@ module Finitio
|
|
81
81
|
uped
|
82
82
|
end
|
83
83
|
|
84
|
+
def unconstrained
|
85
|
+
super_type.unconstrained
|
86
|
+
end
|
87
|
+
|
84
88
|
def ==(other)
|
85
89
|
super || (
|
86
90
|
other.is_a?(SubType) && (other.super_type == super_type) &&
|
@@ -93,5 +97,9 @@ module Finitio
|
|
93
97
|
self.class.hash ^ super_type.hash ^ set_hash(constraints)
|
94
98
|
end
|
95
99
|
|
100
|
+
def resolve_proxies(system)
|
101
|
+
SubType.new(super_type.resolve_proxies(system), constraints, name, metadata)
|
102
|
+
end
|
103
|
+
|
96
104
|
end # class SubType
|
97
105
|
end # module Finitio
|
@@ -70,6 +70,17 @@ module Finitio
|
|
70
70
|
candidates.map(&:name).join('|')
|
71
71
|
end
|
72
72
|
|
73
|
+
def suppremum(other)
|
74
|
+
return self if other == self
|
75
|
+
cs = if (other.is_a?(UnionType))
|
76
|
+
candidates + other.candidates
|
77
|
+
else
|
78
|
+
candidates + [other]
|
79
|
+
end
|
80
|
+
UnionType.new(cs.uniq)
|
81
|
+
end
|
82
|
+
alias :_suppremum :suppremum
|
83
|
+
|
73
84
|
def ==(other)
|
74
85
|
super || (
|
75
86
|
other.is_a?(UnionType) && set_equal?(candidates, other.candidates)
|
@@ -81,5 +92,13 @@ module Finitio
|
|
81
92
|
self.class.hash ^ set_hash(self.candidates)
|
82
93
|
end
|
83
94
|
|
95
|
+
def resolve_proxies(system)
|
96
|
+
UnionType.new(candidates.map{|t| t.resolve_proxies(system)}, name, metadata)
|
97
|
+
end
|
98
|
+
|
99
|
+
def unconstrained
|
100
|
+
UnionType.new(candidates.map{|c| c.unconstrained }, name, metadata)
|
101
|
+
end
|
102
|
+
|
84
103
|
end # class UnionType
|
85
104
|
end # module Finitio
|
data/lib/finitio/version.rb
CHANGED
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
describe Generation do
|
4
|
+
|
5
|
+
subject {
|
6
|
+
Generation.new({
|
7
|
+
:heuristic => Generation::Heuristic::Constant.new,
|
8
|
+
:generators => generators
|
9
|
+
})
|
10
|
+
}
|
11
|
+
|
12
|
+
let(:generators) {
|
13
|
+
{}
|
14
|
+
}
|
15
|
+
|
16
|
+
class SubString < String
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'when called on scalar types' do
|
20
|
+
|
21
|
+
it 'works for nil' do
|
22
|
+
expect(subject.call(nilType)).to eql(nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'works for ints' do
|
26
|
+
expect(subject.call(intType)).to eql(99)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'works for floats' do
|
30
|
+
expect(subject.call(floatType)).to eql(99.99)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'works for strings' do
|
34
|
+
expect(subject.call(stringType)).to eql("Hello world")
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'works for true' do
|
38
|
+
expect(subject.call(trueType)).to be(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'works for false' do
|
42
|
+
expect(subject.call(falseType)).to be(false)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'works on ruby sub types' do
|
46
|
+
expect(subject.call(BuiltinType.new(SubString))).to eql("Hello world")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'when called on Any type' do
|
52
|
+
|
53
|
+
it 'works' do
|
54
|
+
expect {
|
55
|
+
subject.call(anyType)
|
56
|
+
}.not_to raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'when called on an alias type' do
|
62
|
+
|
63
|
+
it 'works' do
|
64
|
+
expect(subject.call(AliasType.new(intType, "x"))).to eql(99)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'when called on an sub type' do
|
70
|
+
|
71
|
+
it 'works' do
|
72
|
+
expect(subject.call(byte)).to eql(99)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'when called on a collection type' do
|
78
|
+
|
79
|
+
it 'works on a SeqType' do
|
80
|
+
got = subject.call(SeqType.new(intType))
|
81
|
+
expect(got).to be_a(Array)
|
82
|
+
expect(got.all?{|x| x==99 }).to be_truthy
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'works on a SetType' do
|
86
|
+
got = subject.call(SetType.new(intType))
|
87
|
+
expect(got).to be_a(Array)
|
88
|
+
expect(got.all?{|x| x==99 }).to be_truthy
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'when called on tuple types' do
|
94
|
+
|
95
|
+
it 'works as expected' do
|
96
|
+
type = TupleType.new(Heading.new [Attribute.new(:i, intType)])
|
97
|
+
expect(subject.call(type)).to eql({i: 99})
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'works as expected' do
|
101
|
+
type = MultiTupleType.new(Heading.new [Attribute.new(:i, intType)])
|
102
|
+
expect(subject.call(type)).to eql({i: 99})
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'when called on relation types' do
|
108
|
+
|
109
|
+
it 'works as expected' do
|
110
|
+
type = RelationType.new(Heading.new [Attribute.new(:i, intType)])
|
111
|
+
expect(subject.call(type)).to eql([{i: 99}])
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'works as expected' do
|
115
|
+
type = MultiRelationType.new(Heading.new [Attribute.new(:i, intType)])
|
116
|
+
expect(subject.call(type)).to eql([{i: 99}])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'when called on a union type' do
|
121
|
+
|
122
|
+
it 'works as expected' do
|
123
|
+
type = UnionType.new([trueType, falseType])
|
124
|
+
expect([true, false].include? subject.call(type)).to be_truthy
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'when called on an AD type' do
|
130
|
+
|
131
|
+
it 'works' do
|
132
|
+
type = AdType.new(Color, [rgb_contract])
|
133
|
+
expect(subject.call(byte)).to eql(99)
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'when examples are provided in metadata' do
|
139
|
+
|
140
|
+
it 'takes the priority' do
|
141
|
+
type = AliasType.new(intType, "X", { examples: [97] })
|
142
|
+
expect(subject.call(type)).to eql(97)
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
describe 'when a generator exists' do
|
148
|
+
|
149
|
+
let(:generators) {
|
150
|
+
{
|
151
|
+
"X" => ->(type, gen, _) { 96 },
|
152
|
+
"Y" => ->(type, gen, world) { world }
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
it 'takes the priority even over examples' do
|
157
|
+
type = AliasType.new(intType, "X", { examples: [97] })
|
158
|
+
expect(subject.call(type)).to eql(96)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'lets pass a world' do
|
162
|
+
type = AliasType.new(intType, "Y", { examples: [97] })
|
163
|
+
expect(subject.call(type, 17)).to eql(17)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|