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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1be4c866c9b4cc67fddb28b39ef618897013cd29
4
- data.tar.gz: 51d2f530a4be64de2a3f9a075e5ff536775454ac
2
+ SHA256:
3
+ metadata.gz: 467a7c5d8dd70fe9b5de2154217a5594182150d6e9c9996ec85c861980c02ecc
4
+ data.tar.gz: cadb1b56c039b7a88456f803733d9c0da9f7d879393674de0fc067c2fb71679b
5
5
  SHA512:
6
- metadata.gz: 9024a94cb06ec0df550904d8b1b2029b0e54956a48d54a95ada3ca9a679fd6314278c2ae6bd524ae6ff171a71f6ec6928cb5bfda0a54cda40ddac07168770308
7
- data.tar.gz: 3d2eee7016ee732383c1deb0ec202c8c2346eb5a3c2610dd1788d2dc6361c30e46a6438f96144822ff991e883cfdb0c03eb50bd7e8e6777724be91345cc6063b
6
+ metadata.gz: 4606b1f8de1df5a7712f8c6546252683928066a18e5e2ed91a96af2e68be552f66e3ccea26d8b6760e9ac5c073fffa416f06ae0ca8001bbac5ca4f2532469f1e
7
+ data.tar.gz: 1d9436c52479abab152422d471b559724e72ea7d933ec8538cf2877e1fa14bebccfc6219dcf662c76758d167653cf47fe10b0332ee2cc118b6e18229826d5eed
@@ -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
@@ -1,4 +1,4 @@
1
- source 'http://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
@@ -1,59 +1,58 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- finitio (0.7.0)
4
+ finitio (0.8.0)
5
5
  citrus (>= 2.4, < 4.0)
6
6
 
7
7
  GEM
8
- remote: http://rubygems.org/
8
+ remote: https://rubygems.org/
9
9
  specs:
10
- awesome_print (1.6.1)
11
- builder (3.2.2)
10
+ awesome_print (1.8.0)
11
+ builder (3.2.3)
12
12
  citrus (3.0.2)
13
- coveralls (0.7.2)
14
- multi_json (~> 1.3)
15
- rest-client (= 1.6.7)
16
- simplecov (>= 0.7)
17
- term-ansicolor (= 1.2.2)
18
- thor (= 0.18.1)
19
- cucumber (1.3.18)
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.1)
25
- diff-lcs (1.2.5)
26
- docile (1.1.5)
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
- mime-types (2.4.3)
30
- multi_json (1.10.1)
31
- multi_test (0.1.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.4.2)
34
- rest-client (1.6.7)
35
- mime-types (>= 1.16)
36
- rspec (3.1.0)
37
- rspec-core (~> 3.1.0)
38
- rspec-expectations (~> 3.1.0)
39
- rspec-mocks (~> 3.1.0)
40
- rspec-core (3.1.7)
41
- rspec-support (~> 3.1.0)
42
- rspec-expectations (3.1.2)
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.1.0)
45
- rspec-mocks (3.1.3)
46
- rspec-support (~> 3.1.0)
47
- rspec-support (3.1.2)
48
- simplecov (0.9.1)
49
- docile (~> 1.1.0)
50
- multi_json (~> 1.0)
51
- simplecov-html (~> 0.8.0)
52
- simplecov-html (0.8.0)
53
- term-ansicolor (1.2.2)
54
- tins (~> 0.8)
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
- 1.16.0
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,10 @@
1
+ module Finitio
2
+ class AdType
3
+
4
+ def generate_data(generator, world = nil)
5
+ infotype = generator.flip_one_out_of(contracts).infotype
6
+ generator.call(infotype, world)
7
+ end
8
+
9
+ end # class AliasType
10
+ end # module Finitio
@@ -0,0 +1,9 @@
1
+ module Finitio
2
+ class AliasType
3
+
4
+ def generate_data(generator, world = nil)
5
+ generator.call(target, world)
6
+ end
7
+
8
+ end # class AliasType
9
+ end # module Finitio
@@ -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,9 @@
1
+ module Finitio
2
+ class BuiltinType
3
+
4
+ def generate_data(generator, world = nil)
5
+ generator.heuristic.call(ruby_type, generator, world)
6
+ end
7
+
8
+ end # class BuiltinType
9
+ 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,8 @@
1
+ module Finitio
2
+ class Generation
3
+ class Heuristic
4
+ end # class Heuristic
5
+ end # class Generation
6
+ end # module Finitio
7
+ require_relative "heuristic/constant"
8
+ require_relative "heuristic/random"
@@ -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
@@ -0,0 +1,13 @@
1
+ module Finitio
2
+ class SeqType
3
+
4
+ def generate_data(generator, world = nil)
5
+ coll = []
6
+ generator.collection_size.times do
7
+ coll << generator.call(elm_type, world)
8
+ end
9
+ coll
10
+ end
11
+
12
+ end # class SeqType
13
+ end # module Finitio
@@ -0,0 +1,13 @@
1
+ module Finitio
2
+ class SetType
3
+
4
+ def generate_data(generator, world = nil)
5
+ coll = []
6
+ generator.collection_size.times do
7
+ coll << generator.call(elm_type, world)
8
+ end
9
+ coll.uniq
10
+ end
11
+
12
+ end # class SetType
13
+ end # module Finitio