finitio 0.7.0.pre.rc4 → 0.10.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 +42 -0
- data/Gemfile +1 -11
- data/Gemfile.lock +101 -54
- data/README.md +89 -13
- data/finitio.gemspec +9 -157
- data/lib/finitio.rb +7 -5
- 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/json_schema.rb +16 -0
- data/lib/finitio/json_schema/ad_type.rb +11 -0
- data/lib/finitio/json_schema/alias_type.rb +9 -0
- data/lib/finitio/json_schema/any_type.rb +9 -0
- data/lib/finitio/json_schema/builtin_type.rb +27 -0
- data/lib/finitio/json_schema/hash_based_type.rb +25 -0
- data/lib/finitio/json_schema/rel_based_type.rb +13 -0
- data/lib/finitio/json_schema/seq_type.rb +12 -0
- data/lib/finitio/json_schema/set_type.rb +13 -0
- data/lib/finitio/json_schema/struct_type.rb +12 -0
- data/lib/finitio/json_schema/sub_type.rb +10 -0
- data/lib/finitio/json_schema/union_type.rb +11 -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 +10 -2
- data/lib/finitio/support/fetch_scope.rb +19 -0
- data/lib/finitio/support/heading.rb +42 -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 +18 -4
- data/lib/finitio/type.rb +19 -0
- data/lib/finitio/type/ad_type.rb +9 -1
- 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 +2 -2
- data/spec/finitio/test_system.rb +0 -11
- 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/json_schema/test_ad_type.rb +20 -0
- data/spec/json_schema/test_alias_type.rb +15 -0
- data/spec/json_schema/test_any_type.rb +11 -0
- data/spec/json_schema/test_builtin_type.rb +51 -0
- data/spec/json_schema/test_multi_relation_type.rb +58 -0
- data/spec/json_schema/test_multi_tuple_type.rb +50 -0
- data/spec/json_schema/test_relation_type.rb +30 -0
- data/spec/json_schema/test_seq_type.rb +18 -0
- data/spec/json_schema/test_set_type.rb +19 -0
- data/spec/json_schema/test_struct_type.rb +18 -0
- data/spec/json_schema/test_sub_type.rb +17 -0
- data/spec/json_schema/test_tuple_type.rb +26 -0
- data/spec/json_schema/test_union_type.rb +17 -0
- data/spec/regression/test_heading_extra_are_proxy_resolved.rb +41 -0
- data/spec/spec_helper.rb +32 -6
- data/spec/support/test_compare_attrs.rb +67 -0
- data/spec/syntax/test_compile.rb +57 -0
- data/spec/system/fixtures/system.fio +2 -0
- data/spec/{finitio → system/fixtures}/with-duplicates.fio +2 -1
- data/spec/system/test_check_and_warn.rb +55 -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 +203 -17
- data/spec/type/proxy_type/test_delegation.rb +0 -37
- data/spec/type/proxy_type/test_resolve.rb +0 -29
@@ -0,0 +1,27 @@
|
|
1
|
+
module Finitio
|
2
|
+
module JsonSchema
|
3
|
+
|
4
|
+
BUILTIN_MAPPING = {
|
5
|
+
NilClass => "null",
|
6
|
+
String => "string",
|
7
|
+
Integer => "integer",
|
8
|
+
Fixnum => "integer",
|
9
|
+
Bignum => "integer",
|
10
|
+
Float => "number",
|
11
|
+
Numeric => "number"
|
12
|
+
}
|
13
|
+
|
14
|
+
end
|
15
|
+
class BuiltinType
|
16
|
+
|
17
|
+
def to_json_schema(*args, &bl)
|
18
|
+
mapped = JsonSchema::BUILTIN_MAPPING[ruby_type]
|
19
|
+
if mapped
|
20
|
+
{ type: mapped }
|
21
|
+
else
|
22
|
+
raise JsonSchema::Error, "Unable to map #{ruby_type} to json-schema"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end # class BuiltinType
|
27
|
+
end # module Finitio
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Finitio
|
2
|
+
module HashBasedType
|
3
|
+
|
4
|
+
def to_json_schema(*args, &bl)
|
5
|
+
base = {
|
6
|
+
type: "object"
|
7
|
+
}
|
8
|
+
unless heading.empty?
|
9
|
+
base[:properties] = heading.inject({}){|ps,a|
|
10
|
+
ps.merge(a.name => a.type.to_json_schema(*args, &bl))
|
11
|
+
}
|
12
|
+
end
|
13
|
+
unless (reqs = heading.select{|a| a.required? }).empty?
|
14
|
+
base[:required] = reqs.map{|a| a.name }
|
15
|
+
end
|
16
|
+
base[:additionalProperties] = if heading.allow_extra?
|
17
|
+
heading.allow_extra.to_json_schema(*args, &bl)
|
18
|
+
else
|
19
|
+
false
|
20
|
+
end
|
21
|
+
base
|
22
|
+
end
|
23
|
+
|
24
|
+
end # module HashBasedType
|
25
|
+
end # module UnionType
|
data/lib/finitio/support.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
module Finitio
|
2
|
+
module Support
|
3
|
+
|
4
|
+
def compare_attrs(h1, h2, &bl)
|
5
|
+
mine, yours = if bl
|
6
|
+
[h1.map(&bl), h2.map(&bl)]
|
7
|
+
elsif h1.is_a?(Hash)
|
8
|
+
[h1.keys, h2.keys]
|
9
|
+
else
|
10
|
+
[h1, h2]
|
11
|
+
end
|
12
|
+
[ mine & yours, mine - yours, yours - mine ]
|
13
|
+
end
|
14
|
+
module_function :compare_attrs
|
15
|
+
|
16
|
+
end # module Support
|
17
|
+
end # module Finitio
|
1
18
|
require_relative 'support/proc_with_code'
|
2
19
|
require_relative 'support/metadata'
|
3
20
|
require_relative 'support/attribute'
|
@@ -6,4 +23,5 @@ require_relative 'support/contract'
|
|
6
23
|
require_relative 'support/heading'
|
7
24
|
require_relative 'support/dress_helper'
|
8
25
|
require_relative 'support/type_factory'
|
26
|
+
require_relative 'support/fetch_scope'
|
9
27
|
require_relative 'support/compilation'
|
@@ -55,5 +55,13 @@ module Finitio
|
|
55
55
|
name.hash ^ type.hash ^ required.hash
|
56
56
|
end
|
57
57
|
|
58
|
+
def resolve_proxies(system)
|
59
|
+
Attribute.new(name, type.resolve_proxies(system), required, metadata)
|
60
|
+
end
|
61
|
+
|
62
|
+
def unconstrained
|
63
|
+
Attribute.new(name, type.unconstrained, required, metadata)
|
64
|
+
end
|
65
|
+
|
58
66
|
end # class Attribute
|
59
67
|
end # module Finitio
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module Finitio
|
2
2
|
class Compilation
|
3
3
|
|
4
|
-
def initialize(system = System.new, factory = TypeFactory.new, source = nil)
|
4
|
+
def initialize(system = System.new, factory = TypeFactory.new, scope = nil, source = nil)
|
5
5
|
@system = system
|
6
6
|
@factory = factory
|
7
|
-
@
|
7
|
+
@scope = scope || FetchScope.new(system, {})
|
8
8
|
@source = source
|
9
9
|
end
|
10
|
-
attr_reader :system, :factory, :
|
10
|
+
attr_reader :system, :factory, :scope, :source
|
11
11
|
|
12
12
|
def self.coerce(arg, source = nil)
|
13
13
|
case arg
|
14
|
-
when NilClass then new(System.new, TypeFactory.new, source)
|
15
|
-
when System then new(arg, arg.factory, source)
|
16
|
-
when TypeFactory then new(System.new, arg, source)
|
14
|
+
when NilClass then new(System.new, TypeFactory.new, nil, source)
|
15
|
+
when System then new(arg, arg.factory, nil, source)
|
16
|
+
when TypeFactory then new(System.new, arg, nil, source)
|
17
17
|
else
|
18
18
|
raise ArgumentError, "Unable to coerce `#{arg}`"
|
19
19
|
end
|
@@ -48,11 +48,8 @@ module Finitio
|
|
48
48
|
Pathname.new(file)
|
49
49
|
end
|
50
50
|
|
51
|
-
def resolve_proxies
|
52
|
-
|
53
|
-
p.resolve(system)
|
54
|
-
end
|
55
|
-
self
|
51
|
+
def resolve_proxies
|
52
|
+
system.resolve_proxies
|
56
53
|
end
|
57
54
|
|
58
55
|
# Delegation to Factory
|
@@ -63,17 +60,10 @@ module Finitio
|
|
63
60
|
}
|
64
61
|
end
|
65
62
|
|
66
|
-
def proxy(*args, &bl)
|
67
|
-
proxy = factory.proxy(*args, &bl)
|
68
|
-
proxies << proxy
|
69
|
-
proxy
|
70
|
-
end
|
71
|
-
|
72
63
|
# Delegation to System
|
73
64
|
|
74
65
|
[
|
75
66
|
:add_type,
|
76
|
-
:fetch,
|
77
67
|
:main,
|
78
68
|
].each do |meth|
|
79
69
|
define_method(meth) do |*args, &bl|
|
@@ -81,5 +71,15 @@ module Finitio
|
|
81
71
|
end
|
82
72
|
end
|
83
73
|
|
74
|
+
# Delegation to FetchScope
|
75
|
+
|
76
|
+
def fetch(type_name, &bl)
|
77
|
+
scope.fetch(type_name, &bl)
|
78
|
+
end
|
79
|
+
|
80
|
+
def with_scope(overrides)
|
81
|
+
Compilation.new(system, factory, scope.with(overrides), source)
|
82
|
+
end
|
83
|
+
|
84
84
|
end # class Compilation
|
85
85
|
end # module Finitio
|
@@ -30,7 +30,7 @@ module Finitio
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def hash
|
33
|
-
|
33
|
+
infotype.hash ^ dresser.hash ^ undresser.hash
|
34
34
|
end
|
35
35
|
|
36
36
|
def ==(other)
|
@@ -38,11 +38,19 @@ module Finitio
|
|
38
38
|
other.is_a?(Contract) &&
|
39
39
|
name == other.name &&
|
40
40
|
infotype == other.infotype &&
|
41
|
-
dresser == other.dresser &&
|
41
|
+
dresser == other.dresser &&
|
42
42
|
undresser == other.undresser
|
43
43
|
)
|
44
44
|
end
|
45
45
|
alias :eql? :==
|
46
46
|
|
47
|
+
def resolve_proxies(system)
|
48
|
+
Contract.new(infotype.resolve_proxies(system), dresser, undresser, name, metadata)
|
49
|
+
end
|
50
|
+
|
51
|
+
def unconstrained
|
52
|
+
Contract.new(infotype.unconstrained, dresser, undresser, name, metadata)
|
53
|
+
end
|
54
|
+
|
47
55
|
end # class Contract
|
48
56
|
end # module Finitio
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Finitio
|
2
|
+
class FetchScope
|
3
|
+
|
4
|
+
def initialize(parent, overrides)
|
5
|
+
@parent, @overrides = parent, overrides
|
6
|
+
end
|
7
|
+
|
8
|
+
def fetch(name, &bl)
|
9
|
+
@overrides.fetch(name) do
|
10
|
+
@parent.fetch(name, &bl)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def with(overrides)
|
15
|
+
FetchScope.new(self, overrides)
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class FetchScope
|
19
|
+
end # module Finitio
|
@@ -61,6 +61,32 @@ module Finitio
|
|
61
61
|
name
|
62
62
|
end
|
63
63
|
|
64
|
+
def looks_similar?(other)
|
65
|
+
return self if other == self
|
66
|
+
shared, mine, yours = Support.compare_attrs(attributes, other.attributes)
|
67
|
+
shared.length >= mine.length && shared.length >= yours.length
|
68
|
+
end
|
69
|
+
|
70
|
+
def suppremum(other)
|
71
|
+
raise ArgumentError unless other.is_a?(Heading)
|
72
|
+
return self if other == self
|
73
|
+
options = { allow_extra: allow_extra? || other.allow_extra? }
|
74
|
+
shared, mine, yours = Support.compare_attrs(attributes, other.attributes)
|
75
|
+
attributes = shared.map{|attr|
|
76
|
+
a1, o1 = self[attr], other[attr]
|
77
|
+
Attribute.new(attr, a1.type.suppremum(o1.type), a1.required && o1.required)
|
78
|
+
}
|
79
|
+
attributes += mine.map{|attrname|
|
80
|
+
attr = self[attrname]
|
81
|
+
Attribute.new(attr.name, attr.type, false)
|
82
|
+
}
|
83
|
+
attributes += yours.map{|attrname|
|
84
|
+
attr = other[attrname]
|
85
|
+
Attribute.new(attr.name, attr.type, false)
|
86
|
+
}
|
87
|
+
Heading.new(attributes, options)
|
88
|
+
end
|
89
|
+
|
64
90
|
def ==(other)
|
65
91
|
return nil unless other.is_a?(Heading)
|
66
92
|
attributes == other.attributes && options == other.options
|
@@ -73,6 +99,21 @@ module Finitio
|
|
73
99
|
attr_reader :attributes, :options
|
74
100
|
protected :attributes, :options
|
75
101
|
|
102
|
+
def resolve_proxies(system)
|
103
|
+
as = attributes.map{|k,a|
|
104
|
+
a.resolve_proxies(system)
|
105
|
+
}
|
106
|
+
opts = options.dup
|
107
|
+
if options[:allow_extra] && options[:allow_extra].is_a?(Type)
|
108
|
+
opts[:allow_extra] = opts[:allow_extra].resolve_proxies(system)
|
109
|
+
end
|
110
|
+
Heading.new(as, opts)
|
111
|
+
end
|
112
|
+
|
113
|
+
def unconstrained
|
114
|
+
Heading.new(attributes.values.map{|a| a.unconstrained }, options)
|
115
|
+
end
|
116
|
+
|
76
117
|
private
|
77
118
|
|
78
119
|
def normalize_attributes(attrs)
|
@@ -83,7 +124,7 @@ module Finitio
|
|
83
124
|
attributes = {}
|
84
125
|
attrs.each do |attr|
|
85
126
|
unless attr.is_a?(Attribute)
|
86
|
-
raise ArgumentError, "Enumerable[Attribute] expected"
|
127
|
+
raise ArgumentError, "Enumerable[Attribute] expected, got a `#{attr.inspect}`"
|
87
128
|
end
|
88
129
|
if attributes[attr.name]
|
89
130
|
raise ArgumentError, "Attribute names must be unique"
|
data/lib/finitio/syntax.rb
CHANGED
data/lib/finitio/syntax/type.rb
CHANGED
@@ -19,9 +19,11 @@ require_relative 'type/relation_type'
|
|
19
19
|
require_relative 'type/union_type'
|
20
20
|
require_relative 'type/type_ref'
|
21
21
|
require_relative 'type/ad_type'
|
22
|
+
require_relative 'type/high_order_type_instantiation'
|
22
23
|
require_relative 'type/contract'
|
23
24
|
require_relative 'type/inline_pair'
|
24
25
|
require_relative 'type/external_pair'
|
25
26
|
require_relative 'type/lambda_expr'
|
26
27
|
require_relative 'type/metadata'
|
27
28
|
require_relative 'type/metadata_attr'
|
29
|
+
require_relative 'type/high_order_vars'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Finitio
|
2
|
+
module Syntax
|
3
|
+
module HighOrderTypeInstantiation
|
4
|
+
include Node
|
5
|
+
|
6
|
+
capture :high
|
7
|
+
capture :vars
|
8
|
+
|
9
|
+
def compile(system)
|
10
|
+
target = system.fetch(high.to_s){
|
11
|
+
raise Error, "No such type `#{high.to_s}`"
|
12
|
+
}
|
13
|
+
raise "#{high} is not a high order type" unless target.is_a?(HighOrderType)
|
14
|
+
|
15
|
+
subs = vars.compile(system).map{|low|
|
16
|
+
system.fetch(low.to_s) {
|
17
|
+
raise Error, "No such type `#{low.to_s}`"
|
18
|
+
}
|
19
|
+
}
|
20
|
+
target.instantiate(system, subs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_ast
|
24
|
+
[:high_order_type_instantiation, high.to_s, lows.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
end # module HighOrderTypeInstantiation
|
28
|
+
end # module Syntax
|
29
|
+
end # module Finitio
|