finitio 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +40 -41
  5. data/lib/finitio/generation.rb +106 -0
  6. data/lib/finitio/generation/ad_type.rb +10 -0
  7. data/lib/finitio/generation/alias_type.rb +9 -0
  8. data/lib/finitio/generation/any_type.rb +11 -0
  9. data/lib/finitio/generation/builtin_type.rb +9 -0
  10. data/lib/finitio/generation/hash_based_type.rb +15 -0
  11. data/lib/finitio/generation/heuristic.rb +8 -0
  12. data/lib/finitio/generation/heuristic/constant.rb +30 -0
  13. data/lib/finitio/generation/heuristic/random.rb +52 -0
  14. data/lib/finitio/generation/rel_based_type.rb +13 -0
  15. data/lib/finitio/generation/seq_type.rb +13 -0
  16. data/lib/finitio/generation/set_type.rb +13 -0
  17. data/lib/finitio/generation/sub_type.rb +9 -0
  18. data/lib/finitio/generation/union_type.rb +10 -0
  19. data/lib/finitio/inference.rb +51 -0
  20. data/lib/finitio/support.rb +18 -0
  21. data/lib/finitio/support/attribute.rb +8 -0
  22. data/lib/finitio/support/compilation.rb +18 -18
  23. data/lib/finitio/support/contract.rb +8 -0
  24. data/lib/finitio/support/fetch_scope.rb +19 -0
  25. data/lib/finitio/support/heading.rb +36 -1
  26. data/lib/finitio/syntax.rb +1 -1
  27. data/lib/finitio/syntax/lexer.citrus +1 -1
  28. data/lib/finitio/syntax/type.rb +2 -0
  29. data/lib/finitio/syntax/type/high_order_type_instantiation.rb +29 -0
  30. data/lib/finitio/syntax/type/high_order_vars.rb +16 -0
  31. data/lib/finitio/syntax/type/type_def.rb +11 -1
  32. data/lib/finitio/syntax/types.citrus +14 -1
  33. data/lib/finitio/system.rb +11 -1
  34. data/lib/finitio/type.rb +19 -0
  35. data/lib/finitio/type/ad_type.rb +8 -0
  36. data/lib/finitio/type/alias_type.rb +8 -0
  37. data/lib/finitio/type/any_type.rb +12 -0
  38. data/lib/finitio/type/builtin_type.rb +4 -0
  39. data/lib/finitio/type/collection_type.rb +15 -0
  40. data/lib/finitio/type/heading_based_type.rb +17 -0
  41. data/lib/finitio/type/high_order_type.rb +39 -0
  42. data/lib/finitio/type/multi_relation_type.rb +4 -0
  43. data/lib/finitio/type/multi_tuple_type.rb +4 -0
  44. data/lib/finitio/type/proxy_type.rb +10 -20
  45. data/lib/finitio/type/relation_type.rb +4 -0
  46. data/lib/finitio/type/seq_type.rb +1 -1
  47. data/lib/finitio/type/struct_type.rb +8 -0
  48. data/lib/finitio/type/sub_type.rb +8 -0
  49. data/lib/finitio/type/tuple_type.rb +4 -0
  50. data/lib/finitio/type/union_type.rb +19 -0
  51. data/lib/finitio/version.rb +1 -1
  52. data/spec/generation/test_generation.rb +169 -0
  53. data/spec/heading/test_looks_similar.rb +45 -0
  54. data/spec/heading/test_suppremum.rb +56 -0
  55. data/spec/inference/test_inference.rb +42 -0
  56. data/spec/spec_helper.rb +31 -6
  57. data/spec/support/test_compare_attrs.rb +67 -0
  58. data/spec/syntax/test_compile.rb +57 -0
  59. data/spec/type/ad_type/test_initialize.rb +1 -8
  60. data/spec/type/relation_type/test_suppremum.rb +104 -0
  61. data/spec/type/seq_type/test_suppremum.rb +54 -0
  62. data/spec/type/set_type/test_suppremum.rb +54 -0
  63. data/spec/type/test_suppremum.rb +49 -0
  64. data/spec/type/test_unconstrained.rb +150 -0
  65. data/spec/type/tuple_type/test_suppremum.rb +119 -0
  66. data/spec/type/union_type/test_suppremum.rb +51 -0
  67. data/tasks/test.rake +1 -1
  68. metadata +183 -144
  69. data/spec/type/proxy_type/test_delegation.rb +0 -37
  70. data/spec/type/proxy_type/test_resolve.rb +0 -29
@@ -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'
@@ -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
@@ -53,5 +53,9 @@ module Finitio
53
53
  self.class.hash ^ ruby_type.hash
54
54
  end
55
55
 
56
+ def resolve_proxies(system)
57
+ self
58
+ end
59
+
56
60
  end # class BuiltinType
57
61
  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
@@ -30,5 +30,9 @@ module Finitio
30
30
  "{{#{heading.to_name}}}"
31
31
  end
32
32
 
33
+ def suppremum(other)
34
+ super(other, RelationType, MultiRelationType)
35
+ end
36
+
33
37
  end # class MultiRelationType
34
38
  end # module Finitio
@@ -25,5 +25,9 @@ module Finitio
25
25
  "{#{heading.to_name}}"
26
26
  end
27
27
 
28
+ def suppremum(other)
29
+ super(other, TupleType, MultiTupleType)
30
+ end
31
+
28
32
  end # class MultiTupleType
29
33
  end # module Finitio
@@ -11,30 +11,20 @@ module Finitio
11
11
  end
12
12
  attr_reader :target_name, :target
13
13
 
14
- [
15
- :representator,
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 resolve(system)
34
- @target = system.fetch(target_name){
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
@@ -36,5 +36,9 @@ module Finitio
36
36
  "{{#{heading.to_name}}}"
37
37
  end
38
38
 
39
+ def suppremum(other)
40
+ super(other, RelationType, MultiRelationType)
41
+ end
42
+
39
43
  end # class RelationType
40
44
  end # module Finitio
@@ -27,7 +27,7 @@ module Finitio
27
27
  include CollectionType
28
28
 
29
29
  def representator
30
- [elmType]
30
+ [elm_type]
31
31
  end
32
32
 
33
33
  def include?(value)
@@ -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
@@ -44,5 +44,9 @@ module Finitio
44
44
  "{#{heading.to_name}}"
45
45
  end
46
46
 
47
+ def suppremum(other)
48
+ super(other, TupleType, MultiTupleType)
49
+ end
50
+
47
51
  end # class TupleType
48
52
  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
@@ -2,7 +2,7 @@ module Finitio
2
2
  module Version
3
3
 
4
4
  MAJOR = 0
5
- MINOR = 7
5
+ MINOR = 8
6
6
  TINY = 0
7
7
 
8
8
  def self.to_s
@@ -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