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.
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