finitio 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 467a7c5d8dd70fe9b5de2154217a5594182150d6e9c9996ec85c861980c02ecc
|
4
|
+
data.tar.gz: cadb1b56c039b7a88456f803733d9c0da9f7d879393674de0fc067c2fb71679b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4606b1f8de1df5a7712f8c6546252683928066a18e5e2ed91a96af2e68be552f66e3ccea26d8b6760e9ac5c073fffa416f06ae0ca8001bbac5ca4f2532469f1e
|
7
|
+
data.tar.gz: 1d9436c52479abab152422d471b559724e72ea7d933ec8538cf2877e1fa14bebccfc6219dcf662c76758d167653cf47fe10b0332ee2cc118b6e18229826d5eed
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# 0.8.0 - 2019/10/21
|
2
|
+
|
3
|
+
* Add `Type#unconstrained` that returns a super type with all user specific
|
4
|
+
constraints removed on sub types, recursively on all non scalar types.
|
5
|
+
|
6
|
+
* Add high-order types, such as `Collection<T> = [T]`
|
7
|
+
|
8
|
+
* Add support for random data generation through `Finitio::Generation`.
|
9
|
+
Please `require 'finitio/generation'` to use it.
|
10
|
+
|
1
11
|
# 0.7.0 / 2019-02-28
|
2
12
|
|
3
13
|
* Implement (basic) @import feature, working with relative paths
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,59 +1,58 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
finitio (0.
|
4
|
+
finitio (0.8.0)
|
5
5
|
citrus (>= 2.4, < 4.0)
|
6
6
|
|
7
7
|
GEM
|
8
|
-
remote:
|
8
|
+
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
awesome_print (1.
|
11
|
-
builder (3.2.
|
10
|
+
awesome_print (1.8.0)
|
11
|
+
builder (3.2.3)
|
12
12
|
citrus (3.0.2)
|
13
|
-
coveralls (0.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
cucumber (1.3.
|
13
|
+
coveralls (0.8.23)
|
14
|
+
json (>= 1.8, < 3)
|
15
|
+
simplecov (~> 0.16.1)
|
16
|
+
term-ansicolor (~> 1.3)
|
17
|
+
thor (>= 0.19.4, < 2.0)
|
18
|
+
tins (~> 1.6)
|
19
|
+
cucumber (1.3.20)
|
20
20
|
builder (>= 2.1.2)
|
21
21
|
diff-lcs (>= 1.1.3)
|
22
22
|
gherkin (~> 2.12)
|
23
23
|
multi_json (>= 1.7.5, < 2.0)
|
24
|
-
multi_test (>= 0.1.
|
25
|
-
diff-lcs (1.
|
26
|
-
docile (1.1
|
24
|
+
multi_test (>= 0.1.2)
|
25
|
+
diff-lcs (1.3)
|
26
|
+
docile (1.3.1)
|
27
27
|
gherkin (2.12.2)
|
28
28
|
multi_json (~> 1.3)
|
29
|
-
|
30
|
-
multi_json (1.
|
31
|
-
multi_test (0.1.
|
29
|
+
json (2.2.0)
|
30
|
+
multi_json (1.13.1)
|
31
|
+
multi_test (0.1.2)
|
32
32
|
path (1.3.3)
|
33
|
-
rake (10.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
rspec-
|
38
|
-
|
39
|
-
rspec-
|
40
|
-
rspec-
|
41
|
-
|
42
|
-
|
33
|
+
rake (10.5.0)
|
34
|
+
rspec (3.8.0)
|
35
|
+
rspec-core (~> 3.8.0)
|
36
|
+
rspec-expectations (~> 3.8.0)
|
37
|
+
rspec-mocks (~> 3.8.0)
|
38
|
+
rspec-core (3.8.0)
|
39
|
+
rspec-support (~> 3.8.0)
|
40
|
+
rspec-expectations (3.8.3)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.8.0)
|
43
|
+
rspec-mocks (3.8.0)
|
43
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
-
rspec-support (~> 3.
|
45
|
-
rspec-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
thor (0.18.1)
|
56
|
-
tins (0.13.2)
|
45
|
+
rspec-support (~> 3.8.0)
|
46
|
+
rspec-support (3.8.0)
|
47
|
+
simplecov (0.16.1)
|
48
|
+
docile (~> 1.1)
|
49
|
+
json (>= 1.8, < 3)
|
50
|
+
simplecov-html (~> 0.10.0)
|
51
|
+
simplecov-html (0.10.2)
|
52
|
+
term-ansicolor (1.7.1)
|
53
|
+
tins (~> 1.0)
|
54
|
+
thor (0.20.3)
|
55
|
+
tins (1.20.2)
|
57
56
|
|
58
57
|
PLATFORMS
|
59
58
|
ruby
|
@@ -68,4 +67,4 @@ DEPENDENCIES
|
|
68
67
|
rspec (~> 3.0)
|
69
68
|
|
70
69
|
BUNDLED WITH
|
71
|
-
|
70
|
+
2.0.1
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require_relative 'generation/heuristic'
|
3
|
+
module Finitio
|
4
|
+
#
|
5
|
+
# This class helps generating random data for a given Finitio type.
|
6
|
+
#
|
7
|
+
# Example
|
8
|
+
#
|
9
|
+
# type = Finitio.system(<<-FIO)
|
10
|
+
# .Integer
|
11
|
+
# FIO
|
12
|
+
# gen = Finitio::Generation.new
|
13
|
+
# gen.call(type)
|
14
|
+
#
|
15
|
+
# Random data is generated for most ruby builtin types, tuples and all sorts
|
16
|
+
# of collections (seq, set, relations).
|
17
|
+
#
|
18
|
+
# You can fine-tune the random data generation through the following means
|
19
|
+
# (the first one wins):
|
20
|
+
#
|
21
|
+
# * By passing generators by type name at construction:
|
22
|
+
#
|
23
|
+
# Finition::Generation.new({
|
24
|
+
# generators: {
|
25
|
+
# "Name" => ->(type, g, world) { "Bernard" }
|
26
|
+
# }
|
27
|
+
# })
|
28
|
+
#
|
29
|
+
# * Through `examples` metadata put on type definitions:
|
30
|
+
#
|
31
|
+
# /- examples: {"Bernard"} -/
|
32
|
+
# Name = .String
|
33
|
+
#
|
34
|
+
class Generation
|
35
|
+
|
36
|
+
DEFAULT_OPTIONS = {
|
37
|
+
|
38
|
+
heuristic: Heuristic::Random.new,
|
39
|
+
|
40
|
+
collection_size: 1..10,
|
41
|
+
|
42
|
+
generators: {
|
43
|
+
"Date" => ->(t,g,w) { g.heuristic.call(Date, g, w) },
|
44
|
+
"Time" => ->(t,g,w) { g.heuristic.call(Time, g, w) },
|
45
|
+
"DateTime" => ->(t,g,w) { g.heuristic.call(DateTime, g, w) }
|
46
|
+
}
|
47
|
+
|
48
|
+
}
|
49
|
+
|
50
|
+
def initialize(options = {})
|
51
|
+
@options = DEFAULT_OPTIONS.merge(options){|k,v1,v2|
|
52
|
+
v1.is_a?(Hash) ? v1.merge(v2) : v2
|
53
|
+
}
|
54
|
+
end
|
55
|
+
attr_reader :options
|
56
|
+
|
57
|
+
def heuristic
|
58
|
+
options[:heuristic]
|
59
|
+
end
|
60
|
+
|
61
|
+
def generators
|
62
|
+
options[:generators]
|
63
|
+
end
|
64
|
+
|
65
|
+
def flip_coin
|
66
|
+
flip_one_out_of(2) == 1
|
67
|
+
end
|
68
|
+
|
69
|
+
def flip_one_out_of(n)
|
70
|
+
case n
|
71
|
+
when Integer then Kernel.rand(n)
|
72
|
+
when Range then Kernel.rand(n)
|
73
|
+
when Enumerable then n[flip_one_out_of(n.size)]
|
74
|
+
else
|
75
|
+
raise "Cannot flip one on #{n}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def collection_size
|
80
|
+
size = options[:collection_size]
|
81
|
+
size = size.is_a?(Proc) ? size.call : size
|
82
|
+
flip_one_out_of(size)
|
83
|
+
end
|
84
|
+
|
85
|
+
def call(type, world = nil)
|
86
|
+
if gen = generators[type.name]
|
87
|
+
gen.call(type, self, world)
|
88
|
+
elsif exs = type.metadata && type.metadata[:examples]
|
89
|
+
flip_one_out_of(exs)
|
90
|
+
else
|
91
|
+
type.generate_data(self, world)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end # class Generation
|
96
|
+
end # module Finitio
|
97
|
+
require_relative 'generation/any_type'
|
98
|
+
require_relative 'generation/builtin_type'
|
99
|
+
require_relative 'generation/seq_type'
|
100
|
+
require_relative 'generation/set_type'
|
101
|
+
require_relative 'generation/hash_based_type'
|
102
|
+
require_relative 'generation/rel_based_type'
|
103
|
+
require_relative 'generation/union_type'
|
104
|
+
require_relative 'generation/alias_type'
|
105
|
+
require_relative 'generation/sub_type'
|
106
|
+
require_relative 'generation/ad_type'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Finitio
|
2
|
+
class AnyType
|
3
|
+
|
4
|
+
def generate_data(generator, world = nil)
|
5
|
+
candidates = [NilClass, String, Integer, Float]
|
6
|
+
type = generator.flip_one_out_of(candidates)
|
7
|
+
generator.heuristic.call(type, generator, world)
|
8
|
+
end
|
9
|
+
|
10
|
+
end # class AnyType
|
11
|
+
end # module Finitio
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Finitio
|
2
|
+
module HashBasedType
|
3
|
+
|
4
|
+
def generate_data(generator, world = nil)
|
5
|
+
tuple = {}
|
6
|
+
heading.each do |a|
|
7
|
+
if a.required or generator.flip_coin
|
8
|
+
tuple[a.name.to_sym] = generator.call(a.type, world)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
tuple
|
12
|
+
end
|
13
|
+
|
14
|
+
end # class HashBasedType
|
15
|
+
end # module Finitio
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Finitio
|
2
|
+
class Generation
|
3
|
+
class Heuristic
|
4
|
+
class Constant < Heuristic
|
5
|
+
|
6
|
+
CONSTANTS = {
|
7
|
+
NilClass => nil,
|
8
|
+
TrueClass => true,
|
9
|
+
FalseClass => false,
|
10
|
+
Integer => 99,
|
11
|
+
Float => 99.99,
|
12
|
+
String => "Hello world",
|
13
|
+
Date => Date.today,
|
14
|
+
Time => Time.now,
|
15
|
+
DateTime => DateTime.now,
|
16
|
+
}
|
17
|
+
|
18
|
+
def call(ruby_type, generator, world = nil)
|
19
|
+
CONSTANTS.fetch(ruby_type) do
|
20
|
+
CONSTANTS.each_pair do |clazz, value|
|
21
|
+
return value if clazz >= ruby_type
|
22
|
+
end
|
23
|
+
throw :unfound
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end # class Constant
|
28
|
+
end # class Heuristic
|
29
|
+
end # class Generation
|
30
|
+
end # module Finition
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Finitio
|
2
|
+
class Generation
|
3
|
+
class Heuristic
|
4
|
+
class Random < Heuristic
|
5
|
+
|
6
|
+
RANDOMERS = {
|
7
|
+
NilClass => nil,
|
8
|
+
|
9
|
+
TrueClass => true,
|
10
|
+
|
11
|
+
FalseClass => false,
|
12
|
+
|
13
|
+
Integer => ->(_,g,_) {
|
14
|
+
g.flip_one_out_of(1_000_000)
|
15
|
+
},
|
16
|
+
|
17
|
+
Float => ->(_,g,_) {
|
18
|
+
g.flip_one_out_of(1_000_000)
|
19
|
+
},
|
20
|
+
|
21
|
+
String => ->(_,g,_) {
|
22
|
+
(1..3).map{ SecureRandom.hex(6) }.join(" ")
|
23
|
+
},
|
24
|
+
|
25
|
+
Date => ->(_,g,_) {
|
26
|
+
Time.at(rand * Time.now.to_i).to_date
|
27
|
+
},
|
28
|
+
|
29
|
+
Time => ->(_,g,_) {
|
30
|
+
Time.at(rand * Time.now.to_i)
|
31
|
+
},
|
32
|
+
|
33
|
+
DateTime => ->(_,g,_) {
|
34
|
+
Time.at(rand * Time.now.to_i).to_datetime
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
def call(ruby_type, generator, world = nil)
|
39
|
+
r = RANDOMERS.fetch(ruby_type) do
|
40
|
+
pair = RANDOMERS.find do |clazz, value|
|
41
|
+
clazz >= ruby_type
|
42
|
+
end
|
43
|
+
throw :unfound unless pair
|
44
|
+
pair.last
|
45
|
+
end
|
46
|
+
r.is_a?(Proc) ? r.call(ruby_type, generator, world) : r
|
47
|
+
end
|
48
|
+
|
49
|
+
end # class Random
|
50
|
+
end # class Heuristic
|
51
|
+
end # class Generation
|
52
|
+
end # module Finition
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Finitio
|
2
|
+
module RelBasedType
|
3
|
+
|
4
|
+
def generate_data(generator, world = nil)
|
5
|
+
coll = []
|
6
|
+
generator.collection_size.times do
|
7
|
+
coll << generator.call(tuple_type, world)
|
8
|
+
end
|
9
|
+
coll.uniq
|
10
|
+
end
|
11
|
+
|
12
|
+
end # module RelBasedType
|
13
|
+
end # module Finitio
|