finitio 0.4.1 → 0.5.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +66 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +34 -30
- data/finitio.gemspec +1 -1
- data/lib/finitio.rb +7 -39
- data/lib/finitio/errors.rb +14 -0
- data/lib/finitio/support.rb +4 -1
- data/lib/finitio/support/attribute.rb +13 -7
- data/lib/finitio/support/compilation.rb +55 -0
- data/lib/finitio/support/constraint.rb +46 -0
- data/lib/finitio/support/contract.rb +33 -0
- data/lib/finitio/support/dress_helper.rb +3 -2
- data/lib/finitio/support/heading.rb +57 -17
- data/lib/finitio/support/metadata.rb +20 -0
- data/lib/finitio/support/type_factory.rb +154 -41
- data/lib/finitio/syntax.rb +16 -31
- data/lib/finitio/syntax/expr.rb +56 -0
- data/lib/finitio/syntax/expr/arith_op.rb +22 -0
- data/lib/finitio/syntax/expr/comparison.rb +22 -0
- data/lib/finitio/syntax/expr/fn_call.rb +24 -0
- data/lib/finitio/syntax/expr/identifier.rb +18 -0
- data/lib/finitio/syntax/expr/literal.rb +19 -0
- data/lib/finitio/syntax/expr/logic_dyadic.rb +22 -0
- data/lib/finitio/syntax/expr/logic_not.rb +21 -0
- data/lib/finitio/syntax/expr/oo_call.rb +24 -0
- data/lib/finitio/syntax/expr/parenthesized.rb +20 -0
- data/lib/finitio/syntax/expr/unary_minus_op.rb +21 -0
- data/lib/finitio/syntax/expressions.citrus +129 -0
- data/lib/finitio/syntax/finitio.citrus +10 -208
- data/lib/finitio/syntax/finitio.sexp +5 -1
- data/lib/finitio/syntax/lexer.citrus +91 -0
- data/lib/finitio/syntax/literal.rb +16 -0
- data/lib/finitio/syntax/literal/boolean.rb +22 -0
- data/lib/finitio/syntax/literal/integer.rb +14 -0
- data/lib/finitio/syntax/literal/real.rb +14 -0
- data/lib/finitio/syntax/literal/string.rb +14 -0
- data/lib/finitio/syntax/literals.citrus +44 -0
- data/lib/finitio/syntax/node.rb +53 -0
- data/lib/finitio/syntax/type.rb +28 -0
- data/lib/finitio/syntax/type/ad_type.rb +29 -0
- data/lib/finitio/syntax/{any_type.rb → type/any_type.rb} +1 -1
- data/lib/finitio/syntax/type/attribute.rb +33 -0
- data/lib/finitio/syntax/{builtin_type.rb → type/builtin_type.rb} +3 -1
- data/lib/finitio/syntax/{constraint_def.rb → type/constraint_def.rb} +4 -3
- data/lib/finitio/syntax/type/constraints.rb +17 -0
- data/lib/finitio/syntax/{contract.rb → type/contract.rb} +9 -3
- data/lib/finitio/syntax/{definitions.rb → type/definitions.rb} +1 -0
- data/lib/finitio/syntax/{expression.rb → type/expression.rb} +2 -1
- data/lib/finitio/syntax/{external_pair.rb → type/external_pair.rb} +3 -1
- data/lib/finitio/syntax/type/heading.rb +30 -0
- data/lib/finitio/syntax/{inline_pair.rb → type/inline_pair.rb} +3 -1
- data/lib/finitio/syntax/{lambda_expr.rb → type/lambda_expr.rb} +3 -0
- data/lib/finitio/syntax/type/main_type.rb +18 -0
- data/lib/finitio/syntax/type/metadata.rb +18 -0
- data/lib/finitio/syntax/type/metadata_attr.rb +15 -0
- data/lib/finitio/syntax/{named_constraint.rb → type/named_constraint.rb} +10 -3
- data/lib/finitio/syntax/type/relation_type.rb +24 -0
- data/lib/finitio/syntax/{seq_type.rb → type/seq_type.rb} +3 -0
- data/lib/finitio/syntax/{set_type.rb → type/set_type.rb} +3 -0
- data/lib/finitio/syntax/type/struct_type.rb +17 -0
- data/lib/finitio/syntax/{sub_type.rb → type/sub_type.rb} +3 -0
- data/lib/finitio/syntax/{system.rb → type/system.rb} +5 -4
- data/lib/finitio/syntax/type/tuple_type.rb +24 -0
- data/lib/finitio/syntax/{type_def.rb → type/type_def.rb} +8 -3
- data/lib/finitio/syntax/{type_ref.rb → type/type_ref.rb} +4 -1
- data/lib/finitio/syntax/{union_type.rb → type/union_type.rb} +1 -0
- data/lib/finitio/syntax/{unnamed_constraint.rb → type/unnamed_constraint.rb} +7 -1
- data/lib/finitio/syntax/types.citrus +196 -0
- data/lib/finitio/system.rb +15 -15
- data/lib/finitio/type.rb +38 -6
- data/lib/finitio/type/ad_type.rb +41 -18
- data/lib/finitio/type/alias_type.rb +37 -0
- data/lib/finitio/type/any_type.rb +7 -3
- data/lib/finitio/type/builtin_type.rb +5 -4
- data/lib/finitio/{support → type}/collection_type.rb +3 -4
- data/lib/finitio/type/hash_based_type.rb +91 -0
- data/lib/finitio/type/heading_based_type.rb +28 -0
- data/lib/finitio/type/multi_relation_type.rb +34 -0
- data/lib/finitio/type/multi_tuple_type.rb +29 -0
- data/lib/finitio/type/proxy_type.rb +40 -0
- data/lib/finitio/type/rel_based_type.rb +42 -0
- data/lib/finitio/type/relation_type.rb +6 -47
- data/lib/finitio/type/seq_type.rb +4 -0
- data/lib/finitio/type/set_type.rb +4 -0
- data/lib/finitio/type/struct_type.rb +84 -0
- data/lib/finitio/type/sub_type.rb +25 -22
- data/lib/finitio/type/tuple_type.rb +6 -57
- data/lib/finitio/type/union_type.rb +12 -5
- data/lib/finitio/version.rb +2 -2
- data/spec/{unit/attribute → attribute}/test_equality.rb +8 -5
- data/spec/{unit/attribute → attribute}/test_fetch_on.rb +5 -5
- data/spec/attribute/test_initialize.rb +26 -0
- data/spec/attribute/test_optional.rb +18 -0
- data/spec/attribute/test_required.rb +18 -0
- data/spec/attribute/test_to_name.rb +20 -0
- data/spec/constraint/test_anonymous.rb +20 -0
- data/spec/constraint/test_equality.rb +39 -0
- data/spec/constraint/test_name.rb +20 -0
- data/spec/constraint/test_named.rb +20 -0
- data/spec/constraint/test_triple_equal.rb +13 -0
- data/spec/{unit/qrb/system.q → finitio/system.fio} +0 -0
- data/spec/{unit/qrb → finitio}/test_ast.rb +0 -0
- data/spec/finitio/test_parse.rb +23 -0
- data/spec/{unit/qrb/test_parse.rb → finitio/test_system.rb} +6 -6
- data/spec/heading/test_allow_extra.rb +24 -0
- data/spec/{unit/heading → heading}/test_each.rb +2 -2
- data/spec/heading/test_equality.rb +38 -0
- data/spec/heading/test_hash.rb +38 -0
- data/spec/heading/test_hash_get.rb +17 -0
- data/spec/{unit/heading → heading}/test_initialize.rb +2 -2
- data/spec/heading/test_multi.rb +57 -0
- data/spec/{unit/heading → heading}/test_size.rb +0 -0
- data/spec/heading/test_to_name.rb +58 -0
- data/spec/spec_helper.rb +17 -1
- data/spec/syntax/expr/test_free_variables.rb +46 -0
- data/spec/syntax/expr/test_to_proc_source.rb +43 -0
- data/spec/{unit/syntax → syntax}/nodes/test_ad_type.rb +26 -26
- data/spec/{unit/syntax → syntax}/nodes/test_any_type.rb +2 -2
- data/spec/syntax/nodes/test_attribute.rb +65 -0
- data/spec/{unit/syntax → syntax}/nodes/test_builtin_type.rb +5 -5
- data/spec/{unit/syntax → syntax}/nodes/test_comment.rb +1 -1
- data/spec/{unit/syntax → syntax}/nodes/test_constraint_def.rb +3 -8
- data/spec/{unit/syntax → syntax}/nodes/test_constraints.rb +21 -16
- data/spec/{unit/syntax → syntax}/nodes/test_contract.rb +28 -35
- data/spec/{unit/syntax → syntax}/nodes/test_expression.rb +13 -5
- data/spec/{unit/syntax → syntax}/nodes/test_heading.rb +25 -7
- data/spec/syntax/nodes/test_metadata.rb +28 -0
- data/spec/{unit/syntax → syntax}/nodes/test_named_constraint.rb +8 -8
- data/spec/syntax/nodes/test_relation_type.rb +84 -0
- data/spec/{unit/syntax → syntax}/nodes/test_seq_type.rb +4 -4
- data/spec/{unit/syntax → syntax}/nodes/test_set_type.rb +4 -4
- data/spec/{unit/syntax → syntax}/nodes/test_spacing.rb +1 -1
- data/spec/syntax/nodes/test_struct_type.rb +38 -0
- data/spec/{unit/syntax → syntax}/nodes/test_sub_type.rb +14 -14
- data/spec/{unit/syntax → syntax}/nodes/test_system.rb +3 -3
- data/spec/syntax/nodes/test_tuple_type.rb +94 -0
- data/spec/syntax/nodes/test_type_def.rb +57 -0
- data/spec/{unit/syntax → syntax}/nodes/test_type_ref.rb +3 -3
- data/spec/{unit/syntax → syntax}/nodes/test_union_type.rb +3 -3
- data/spec/{unit/syntax → syntax}/nodes/test_unnamed_constraint.rb +7 -7
- data/spec/syntax/test_compile.rb +41 -0
- data/spec/{unit/syntax → syntax}/test_compile_type.rb +1 -1
- data/spec/{unit/system → system}/test_add_type.rb +6 -6
- data/spec/{unit/system → system}/test_dsl.rb +2 -2
- data/spec/{unit/system → system}/test_dup.rb +4 -4
- data/spec/{unit/system → system}/test_fetch.rb +4 -4
- data/spec/{unit/system → system}/test_get_type.rb +2 -2
- data/spec/{unit/system → system}/test_initialize.rb +0 -0
- data/spec/test_finitio.rb +8 -0
- data/spec/{unit/type → type}/ad_type/test_default_name.rb +1 -2
- data/spec/{unit/type → type}/ad_type/test_dress.rb +19 -9
- data/spec/{unit/type → type}/ad_type/test_include.rb +3 -3
- data/spec/{unit/type → type}/ad_type/test_initialize.rb +15 -8
- data/spec/{unit/type → type}/ad_type/test_name.rb +2 -2
- data/spec/type/alias_type/test_default_name.rb +10 -0
- data/spec/type/alias_type/test_delegation.rb +29 -0
- data/spec/type/alias_type/test_name.rb +10 -0
- data/spec/{unit/type → type}/any_type/test_default_name.rb +1 -1
- data/spec/{unit/type → type}/any_type/test_dress.rb +0 -0
- data/spec/{unit/type → type}/any_type/test_equality.rb +4 -4
- data/spec/{unit/type → type}/any_type/test_include.rb +2 -2
- data/spec/{unit/type → type}/any_type/test_initialize.rb +0 -0
- data/spec/{unit/type → type}/any_type/test_name.rb +2 -2
- data/spec/{unit/type → type}/builtin_type/test_default_name.rb +1 -1
- data/spec/{unit/type → type}/builtin_type/test_dress.rb +3 -3
- data/spec/{unit/type → type}/builtin_type/test_equality.rb +4 -4
- data/spec/{unit/type → type}/builtin_type/test_include.rb +2 -2
- data/spec/{unit/type → type}/builtin_type/test_initialize.rb +1 -1
- data/spec/{unit/type → type}/builtin_type/test_name.rb +2 -2
- data/spec/type/multi_relation_type/test_default_name.rb +19 -0
- data/spec/type/multi_relation_type/test_dress.rb +206 -0
- data/spec/type/multi_relation_type/test_equality.rb +36 -0
- data/spec/type/multi_relation_type/test_include.rb +89 -0
- data/spec/type/multi_relation_type/test_initialize.rb +29 -0
- data/spec/type/multi_relation_type/test_name.rb +27 -0
- data/spec/type/multi_tuple_type/test_default_name.rb +17 -0
- data/spec/type/multi_tuple_type/test_dress.rb +146 -0
- data/spec/type/multi_tuple_type/test_equality.rb +32 -0
- data/spec/type/multi_tuple_type/test_include.rb +73 -0
- data/spec/type/multi_tuple_type/test_initialize.rb +30 -0
- data/spec/type/multi_tuple_type/test_name.rb +24 -0
- data/spec/type/proxy_type/test_delegation.rb +37 -0
- data/spec/type/proxy_type/test_resolve.rb +29 -0
- data/spec/{unit/type → type}/relation_type/test_default_name.rb +0 -0
- data/spec/{unit/type → type}/relation_type/test_dress.rb +24 -24
- data/spec/{unit/type → type}/relation_type/test_equality.rb +6 -6
- data/spec/{unit/type → type}/relation_type/test_include.rb +4 -4
- data/spec/{unit/type → type}/relation_type/test_initialize.rb +2 -2
- data/spec/{unit/type → type}/relation_type/test_name.rb +0 -0
- data/spec/{unit/type → type}/seq_type/test_default_name.rb +0 -0
- data/spec/{unit/type → type}/seq_type/test_dress.rb +5 -5
- data/spec/{unit/type → type}/seq_type/test_equality.rb +4 -4
- data/spec/{unit/type → type}/seq_type/test_include.rb +4 -4
- data/spec/{unit/type → type}/seq_type/test_initialize.rb +3 -3
- data/spec/{unit/type → type}/seq_type/test_name.rb +0 -0
- data/spec/{unit/type → type}/set_type/test_default_name.rb +0 -0
- data/spec/{unit/type → type}/set_type/test_dress.rb +8 -8
- data/spec/{unit/type → type}/set_type/test_equality.rb +4 -4
- data/spec/{unit/type → type}/set_type/test_include.rb +4 -4
- data/spec/{unit/type → type}/set_type/test_initialize.rb +3 -3
- data/spec/{unit/type → type}/set_type/test_name.rb +0 -0
- data/spec/type/struct_type/test_default_name.rb +10 -0
- data/spec/type/struct_type/test_dress.rb +105 -0
- data/spec/type/struct_type/test_equality.rb +28 -0
- data/spec/type/struct_type/test_include.rb +40 -0
- data/spec/type/struct_type/test_initialize.rb +22 -0
- data/spec/type/struct_type/test_name.rb +20 -0
- data/spec/{unit/type → type}/sub_type/test_default_name.rb +2 -2
- data/spec/{unit/type → type}/sub_type/test_dress.rb +14 -14
- data/spec/type/sub_type/test_equality.rb +46 -0
- data/spec/{unit/type → type}/sub_type/test_include.rb +6 -6
- data/spec/type/sub_type/test_initialize.rb +13 -0
- data/spec/{unit/type → type}/sub_type/test_name.rb +4 -4
- data/spec/{unit/type → type}/tuple_type/test_default_name.rb +0 -0
- data/spec/{unit/type → type}/tuple_type/test_dress.rb +18 -18
- data/spec/{unit/type → type}/tuple_type/test_equality.rb +6 -6
- data/spec/{unit/type → type}/tuple_type/test_include.rb +4 -4
- data/spec/{unit/type → type}/tuple_type/test_initialize.rb +4 -4
- data/spec/{unit/type → type}/tuple_type/test_name.rb +0 -0
- data/spec/{unit/type → type}/union_type/test_default_name.rb +0 -0
- data/spec/{unit/type → type}/union_type/test_dress.rb +7 -6
- data/spec/{unit/type → type}/union_type/test_equality.rb +7 -7
- data/spec/{unit/type → type}/union_type/test_include.rb +3 -3
- data/spec/{unit/type → type}/union_type/test_initialize.rb +3 -3
- data/spec/{unit/type → type}/union_type/test_name.rb +0 -0
- data/spec/{unit/type_factory → type_factory}/dsl/test_adt.rb +4 -4
- data/spec/{unit/type_factory → type_factory}/dsl/test_any.rb +1 -1
- data/spec/{unit/type_factory → type_factory}/dsl/test_attribute.rb +16 -2
- data/spec/{unit/type_factory → type_factory}/dsl/test_attributes.rb +1 -1
- data/spec/{unit/type_factory → type_factory}/dsl/test_builtin.rb +3 -3
- data/spec/type_factory/dsl/test_multi_relation.rb +39 -0
- data/spec/type_factory/dsl/test_multi_tuple.rb +37 -0
- data/spec/{unit/type_factory → type_factory}/dsl/test_relation.rb +6 -6
- data/spec/{unit/type_factory → type_factory}/dsl/test_seq.rb +4 -4
- data/spec/{unit/type_factory → type_factory}/dsl/test_set.rb +4 -4
- data/spec/type_factory/dsl/test_struct.rb +45 -0
- data/spec/{unit/type_factory → type_factory}/dsl/test_subtype.rb +10 -8
- data/spec/{unit/type_factory → type_factory}/dsl/test_tuple.rb +5 -5
- data/spec/{unit/type_factory → type_factory}/dsl/test_union.rb +6 -6
- data/spec/{unit/type_factory → type_factory}/factory/test_builtin.rb +1 -1
- data/spec/{unit/type_factory → type_factory}/factory/test_seq_type.rb +2 -2
- data/spec/{unit/type_factory → type_factory}/factory/test_set_type.rb +2 -2
- data/spec/type_factory/factory/test_struct_type.rb +18 -0
- data/spec/{unit/type_factory → type_factory}/factory/test_sub_type.rb +7 -7
- data/spec/{unit/type_factory → type_factory}/factory/test_tuple_type.rb +4 -4
- metadata +398 -286
- data/lib/finitio/data_type.rb +0 -29
- data/lib/finitio/syntax/ad_type.rb +0 -32
- data/lib/finitio/syntax/attribute.rb +0 -15
- data/lib/finitio/syntax/constraints.rb +0 -22
- data/lib/finitio/syntax/heading.rb +0 -19
- data/lib/finitio/syntax/relation_type.rb +0 -15
- data/lib/finitio/syntax/support.rb +0 -13
- data/lib/finitio/syntax/tuple_type.rb +0 -15
- data/spec/acceptance/Finitio/test_default.rb +0 -96
- data/spec/acceptance/Finitio/test_parsing.rb +0 -15
- data/spec/acceptance/ad_type/test_in_finitio.rb +0 -82
- data/spec/acceptance/ad_type/test_in_ruby.rb +0 -60
- data/spec/unit/attribute/test_initialize.rb +0 -13
- data/spec/unit/attribute/test_to_name.rb +0 -10
- data/spec/unit/heading/test_equality.rb +0 -28
- data/spec/unit/heading/test_to_name.rb +0 -32
- data/spec/unit/syntax/nodes/test_attribute.rb +0 -38
- data/spec/unit/syntax/nodes/test_relation_type.rb +0 -59
- data/spec/unit/syntax/nodes/test_tuple_type.rb +0 -59
- data/spec/unit/syntax/nodes/test_type_def.rb +0 -33
- data/spec/unit/test_finitio.rb +0 -15
- data/spec/unit/type/sub_type/test_equality.rb +0 -34
- data/spec/unit/type/sub_type/test_initialize.rb +0 -16
data/lib/finitio/type/ad_type.rb
CHANGED
@@ -48,29 +48,36 @@ module Finitio
|
|
48
48
|
#
|
49
49
|
class AdType < Type
|
50
50
|
|
51
|
-
def initialize(ruby_type, contracts, name = nil)
|
51
|
+
def initialize(ruby_type, contracts, name = nil, metadata = nil)
|
52
52
|
unless ruby_type.nil? or ruby_type.is_a?(Module)
|
53
53
|
raise ArgumentError, "Module expected, got `#{ruby_type}`"
|
54
54
|
end
|
55
|
-
unless contracts.is_a?(
|
56
|
-
|
57
|
-
|
58
|
-
invalid = contracts.values.reject{|v|
|
59
|
-
v.is_a?(Array) and v.size == 3 and v[0].is_a?(Type) and \
|
60
|
-
v[1].respond_to?(:call) and v[2].respond_to?(:call)
|
61
|
-
}
|
62
|
-
unless invalid.empty?
|
63
|
-
raise ArgumentError, "Invalid contracts `#{invalid}`"
|
55
|
+
unless contracts.is_a?(Array) &&
|
56
|
+
contracts.all?{|c| c.is_a?(Contract) }
|
57
|
+
raise ArgumentError, "[Contract] expected, got `#{contracts}`"
|
64
58
|
end
|
65
59
|
|
66
|
-
super(name)
|
60
|
+
super(name, metadata)
|
67
61
|
@ruby_type = ruby_type
|
68
62
|
@contracts = contracts.freeze
|
69
63
|
end
|
70
64
|
attr_reader :ruby_type, :contracts
|
71
65
|
|
66
|
+
alias :representator :ruby_type
|
67
|
+
|
68
|
+
def ruby_type=(ruby_type)
|
69
|
+
@ruby_type = ruby_type
|
70
|
+
@contracts.each do |contract|
|
71
|
+
contract.bind_ruby_type(ruby_type)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](name)
|
76
|
+
contracts.find{|c| c.name == name }
|
77
|
+
end
|
78
|
+
|
72
79
|
def contract_names
|
73
|
-
contracts.
|
80
|
+
contracts.map(&:name)
|
74
81
|
end
|
75
82
|
|
76
83
|
def default_name
|
@@ -85,27 +92,43 @@ module Finitio
|
|
85
92
|
# Up should be idempotent with respect to the ADT
|
86
93
|
return value if ruby_type and value.is_a?(ruby_type)
|
87
94
|
|
95
|
+
# Dressed value and first exception
|
96
|
+
dressed, error = nil, nil
|
97
|
+
|
88
98
|
# Try each contract in turn. Do nothing on TypeError as
|
89
99
|
# the next candidate could be the good one! Return the
|
90
100
|
# first successfully dressed.
|
91
|
-
contracts.
|
101
|
+
contracts.each do |contract|
|
92
102
|
|
93
103
|
# First make the dress transformation on the information type
|
94
104
|
success, dressed = handler.just_try do
|
95
|
-
infotype.dress(value, handler)
|
105
|
+
contract.infotype.dress(value, handler)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Save very first error on failure
|
109
|
+
unless success
|
110
|
+
error ||= dressed
|
111
|
+
next
|
96
112
|
end
|
97
|
-
next unless success
|
98
113
|
|
99
114
|
# Seems nice, just try to get one stage higher now
|
100
115
|
success, dressed = handler.just_try(StandardError) do
|
101
|
-
dresser.call(dressed)
|
116
|
+
contract.dresser.call(dressed)
|
102
117
|
end
|
103
|
-
return dressed if success
|
104
118
|
|
119
|
+
if success
|
120
|
+
if ruby_type && !dressed.is_a?(ruby_type)
|
121
|
+
raise "Invalid IC dresser (#{contract.dresser}):"\
|
122
|
+
" #{ruby_type} expected, got #{dressed.class}"
|
123
|
+
end
|
124
|
+
return dressed
|
125
|
+
else
|
126
|
+
error ||= dressed
|
127
|
+
end
|
105
128
|
end
|
106
129
|
|
107
130
|
# No one succeeded, just fail
|
108
|
-
handler.failed!(self, value)
|
131
|
+
handler.failed!(self, value, error)
|
109
132
|
end
|
110
133
|
|
111
134
|
end # class AdType
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Finitio
|
2
|
+
class AliasType < Type
|
3
|
+
|
4
|
+
def initialize(target, name, metadata = nil)
|
5
|
+
unless target.is_a?(Type)
|
6
|
+
raise ArgumentError, "Type expected for target type, got `#{target}`"
|
7
|
+
end
|
8
|
+
if name.nil?
|
9
|
+
raise ArgumentError, "Alias name cannot be nil"
|
10
|
+
end
|
11
|
+
|
12
|
+
super(name, metadata)
|
13
|
+
@target = target
|
14
|
+
end
|
15
|
+
attr_reader :target
|
16
|
+
|
17
|
+
def default_name
|
18
|
+
@name
|
19
|
+
end
|
20
|
+
|
21
|
+
[
|
22
|
+
:representator,
|
23
|
+
:dress,
|
24
|
+
:undress,
|
25
|
+
:include?,
|
26
|
+
:==,
|
27
|
+
:eql?,
|
28
|
+
:hash,
|
29
|
+
:to_s
|
30
|
+
].each do |meth|
|
31
|
+
define_method(meth) do |*args, &bl|
|
32
|
+
@target.send(meth, *args, &bl)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end # class AliasType
|
37
|
+
end # module Finitio
|
@@ -18,14 +18,18 @@ module Finitio
|
|
18
18
|
#
|
19
19
|
class AnyType < Type
|
20
20
|
|
21
|
-
def initialize(name = nil)
|
22
|
-
super(name)
|
21
|
+
def initialize(name = nil, metadata = nil)
|
22
|
+
super(name, metadata)
|
23
23
|
end
|
24
24
|
|
25
25
|
def default_name
|
26
26
|
"Any"
|
27
27
|
end
|
28
28
|
|
29
|
+
def representator
|
30
|
+
Object
|
31
|
+
end
|
32
|
+
|
29
33
|
def include?(value)
|
30
34
|
true
|
31
35
|
end
|
@@ -35,7 +39,7 @@ module Finitio
|
|
35
39
|
end
|
36
40
|
|
37
41
|
def ==(other)
|
38
|
-
other.is_a?(AnyType)
|
42
|
+
super || other.is_a?(AnyType)
|
39
43
|
end
|
40
44
|
alias :eql? :==
|
41
45
|
|
@@ -21,12 +21,14 @@ module Finitio
|
|
21
21
|
#
|
22
22
|
class BuiltinType < Type
|
23
23
|
|
24
|
-
def initialize(ruby_type, name = nil)
|
25
|
-
super(name)
|
24
|
+
def initialize(ruby_type, name = nil, metadata = nil)
|
25
|
+
super(name, metadata)
|
26
26
|
@ruby_type = ruby_type
|
27
27
|
end
|
28
28
|
attr_reader :ruby_type
|
29
29
|
|
30
|
+
alias :representator :ruby_type
|
31
|
+
|
30
32
|
def default_name
|
31
33
|
@ruby_type.name.to_s
|
32
34
|
end
|
@@ -43,8 +45,7 @@ module Finitio
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def ==(other)
|
46
|
-
|
47
|
-
other.ruby_type==ruby_type
|
48
|
+
super || (other.is_a?(BuiltinType) && other.ruby_type==ruby_type)
|
48
49
|
end
|
49
50
|
alias :eql? :==
|
50
51
|
|
@@ -1,19 +1,18 @@
|
|
1
1
|
module Finitio
|
2
2
|
module CollectionType
|
3
3
|
|
4
|
-
def initialize(elm_type, name = nil)
|
4
|
+
def initialize(elm_type, name = nil, metadata = nil)
|
5
5
|
unless elm_type.is_a?(Type)
|
6
6
|
raise ArgumentError, "Finitio::Type expected, got `#{elm_type}`"
|
7
7
|
end
|
8
8
|
|
9
|
-
super(name)
|
9
|
+
super(name, metadata)
|
10
10
|
@elm_type = elm_type
|
11
11
|
end
|
12
12
|
attr_reader :elm_type
|
13
13
|
|
14
14
|
def ==(other)
|
15
|
-
|
16
|
-
elm_type == other.elm_type
|
15
|
+
super || (other.is_a?(self.class) && elm_type == other.elm_type)
|
17
16
|
end
|
18
17
|
alias :eql? :==
|
19
18
|
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Finitio
|
2
|
+
module HashBasedType
|
3
|
+
|
4
|
+
def representator
|
5
|
+
rep = {}
|
6
|
+
heading.each do |attr|
|
7
|
+
rep[attr.name] = rep[attr.type.representator]
|
8
|
+
end
|
9
|
+
rep
|
10
|
+
end
|
11
|
+
|
12
|
+
def include?(value)
|
13
|
+
value.is_a?(Hash) &&
|
14
|
+
valid_attrs?(value) &&
|
15
|
+
heading.all?{|a|
|
16
|
+
value.has_key?(a.name) ? a.type.include?(value[a.name]) : true
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Convert `value` (supposed to be Hash) to a Tuple, by checking attributes
|
21
|
+
# and applying `dress` on them in turn. Raise an error if any attribute
|
22
|
+
# is missing or unrecognized, as well as if any sub transformation fails.
|
23
|
+
def dress(value, handler = DressHelper.new)
|
24
|
+
handler.failed!(self, value) unless looks_a_tuple?(value)
|
25
|
+
|
26
|
+
# Check for extra attributes
|
27
|
+
unless heading.allow_extra? or (extra = extra_attrs(value, true)).empty?
|
28
|
+
handler.fail!("Unrecognized attribute `#{extra.first}`")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Check for missing attributes
|
32
|
+
unless (missing = missing_attrs(value, true)).empty?
|
33
|
+
handler.fail!("Missing attribute `#{missing.first}`")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Uped values, i.e. tuple under construction
|
37
|
+
uped = {}
|
38
|
+
|
39
|
+
# Up each attribute in turn now. Fail on missing ones.
|
40
|
+
heading.each do |attribute|
|
41
|
+
present = true
|
42
|
+
val = attribute.fetch_on(value){ present = false }
|
43
|
+
next unless present
|
44
|
+
handler.deeper(attribute.name) do
|
45
|
+
uped[attribute.name] = attribute.type.dress(val, handler)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
uped
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def looks_a_tuple?(value)
|
55
|
+
value.is_a?(Hash) or value.respond_to?(:fetch)
|
56
|
+
end
|
57
|
+
|
58
|
+
def attr_names
|
59
|
+
@attr_names ||= heading.map(&:name)
|
60
|
+
end
|
61
|
+
|
62
|
+
def req_attr_names
|
63
|
+
@req_attr_names ||= heading.select(&:required).map(&:name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def attrs(as, to_s)
|
67
|
+
to_s ? as.map(&:to_s) : as
|
68
|
+
end
|
69
|
+
|
70
|
+
def extra_attrs(value, to_s = false)
|
71
|
+
attrs(value.keys, to_s) - attrs(attr_names, to_s)
|
72
|
+
end
|
73
|
+
|
74
|
+
def extra_attr?(value, to_s = false)
|
75
|
+
!extra_attrs(value, to_s).empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
def missing_attrs(value, to_s = false)
|
79
|
+
attrs(req_attr_names, to_s) - attrs(value.keys, to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
def missing_attr?(value, to_s = false)
|
83
|
+
!missing_attrs(value, to_s).empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
def valid_attrs?(value, to_s = false)
|
87
|
+
(heading.allow_extra? || !extra_attr?(value, to_s)) && !missing_attr?(value)
|
88
|
+
end
|
89
|
+
|
90
|
+
end # module HashBasedType
|
91
|
+
end # module Finitio
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Finitio
|
2
|
+
module HeadingBasedType
|
3
|
+
|
4
|
+
def initialize(heading, name = nil, metadata = nil)
|
5
|
+
unless heading.is_a?(Heading)
|
6
|
+
raise ArgumentError, "Heading expected, got `#{heading}`"
|
7
|
+
end
|
8
|
+
|
9
|
+
super(name, metadata)
|
10
|
+
@heading = heading
|
11
|
+
end
|
12
|
+
attr_reader :heading
|
13
|
+
|
14
|
+
def [](attrname)
|
15
|
+
heading.fetch(attrname)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
super || (other.is_a?(self.class) && heading == other.heading)
|
20
|
+
end
|
21
|
+
alias :eql? :==
|
22
|
+
|
23
|
+
def hash
|
24
|
+
self.class.hash ^ heading.hash
|
25
|
+
end
|
26
|
+
|
27
|
+
end # module HeadingBasedType
|
28
|
+
end # module Finitio
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Finitio
|
2
|
+
#
|
3
|
+
# The MultiRelation type generator allows capturing sets of information
|
4
|
+
# facts, but allowing optional attributes. E. g.,
|
5
|
+
#
|
6
|
+
# ColoredPoints = {{ point: Point, color :? Color }}
|
7
|
+
#
|
8
|
+
# This class allows capturing those types, in a way similar to
|
9
|
+
# MultiTupleType:
|
10
|
+
#
|
11
|
+
# ColoredPoints = MultiRelationType.new( Heading[...] )
|
12
|
+
#
|
13
|
+
# A ruby Set is used as concrete representation, and will contain hashes
|
14
|
+
# that are valid representations of the associated multi tuple type:
|
15
|
+
#
|
16
|
+
# R(ColoredPoints) = Set[ R({...}) ] = Set[Hash[...]]
|
17
|
+
#
|
18
|
+
# Accordingly, the dress transformation function has the signature below.
|
19
|
+
# It expects an Enumerable as input and fails if any duplicate is found
|
20
|
+
# (after tuple transformation), or if any tuple fails at being transformed.
|
21
|
+
#
|
22
|
+
# dress :: Alpha -> ColoredPoints throws TypeError
|
23
|
+
# dress :: Object -> Set[Hash[...]] throws TypeError
|
24
|
+
#
|
25
|
+
class MultiRelationType < Type
|
26
|
+
include HeadingBasedType
|
27
|
+
include RelBasedType
|
28
|
+
|
29
|
+
def default_name
|
30
|
+
"{{#{heading.to_name}}}"
|
31
|
+
end
|
32
|
+
|
33
|
+
end # class MultiRelationType
|
34
|
+
end # module Finitio
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Finitio
|
2
|
+
#
|
3
|
+
# The MultiTuple type generator allows capturing information *facts* with
|
4
|
+
# optional attributes. For instance, a Point type with an optional color
|
5
|
+
# could be defined as follows:
|
6
|
+
#
|
7
|
+
# Point = { r: Length, theta: Angle, color :? Color }
|
8
|
+
#
|
9
|
+
# This class allows capturing those information types. Note that it is
|
10
|
+
# actually syntactic sugar over union types:
|
11
|
+
#
|
12
|
+
# Point = { r: Length, theta: Angle }
|
13
|
+
# | { r: Length, theta: Angle, color: Color }
|
14
|
+
#
|
15
|
+
# A Hash with Symbol as keys is used as concrete ruby representation for
|
16
|
+
# multi tuples. The values map to the concrete representations of each
|
17
|
+
# attribute type. The dress function is similar to the one of TupleType
|
18
|
+
# but allows optional attributes to be omitted
|
19
|
+
#
|
20
|
+
class MultiTupleType < Type
|
21
|
+
include HeadingBasedType
|
22
|
+
include HashBasedType
|
23
|
+
|
24
|
+
def default_name
|
25
|
+
"{#{heading.to_name}}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end # class MultiTupleType
|
29
|
+
end # module Finitio
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Finitio
|
2
|
+
class ProxyType < Type
|
3
|
+
|
4
|
+
def initialize(target_name, target = nil)
|
5
|
+
unless target_name.is_a?(String)
|
6
|
+
raise ArgumentError, "String expected for type name, got `#{target_name}`"
|
7
|
+
end
|
8
|
+
|
9
|
+
@target_name = target_name
|
10
|
+
@target = target
|
11
|
+
end
|
12
|
+
attr_reader :target_name, :target
|
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, "Proxy not resolved" unless @target
|
29
|
+
@target.send(meth, *args, &bl)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def resolve(system)
|
34
|
+
@target = system.fetch(target_name) do
|
35
|
+
raise Error, "No such type `#{target_name}`"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end # class ProxyType
|
40
|
+
end # module Finitio
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Finitio
|
2
|
+
module RelBasedType
|
3
|
+
|
4
|
+
def representator
|
5
|
+
[tuple_type.representator]
|
6
|
+
end
|
7
|
+
|
8
|
+
def include?(value)
|
9
|
+
value.is_a?(Set) && value.all?{|tuple|
|
10
|
+
tuple_type.include?(tuple)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Apply the corresponding TupleType's `dress` to every element of `value`
|
15
|
+
# (any enumerable). Return a Set of transformed tuples. Fail if anything
|
16
|
+
# goes wrong transforming tuples or if duplicates are found.
|
17
|
+
def dress(value, handler = DressHelper.new)
|
18
|
+
handler.failed!(self, value) unless value.respond_to?(:each)
|
19
|
+
|
20
|
+
# Up every tuple and keep results in a Set
|
21
|
+
set = Set.new
|
22
|
+
handler.iterate(value) do |tuple, index|
|
23
|
+
tuple = tuple_type.dress(tuple, handler)
|
24
|
+
handler.fail!("Duplicate tuple") if set.include?(tuple)
|
25
|
+
set << tuple
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return built tuples
|
29
|
+
set
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def tuple_type
|
35
|
+
@tuple_type ||= begin
|
36
|
+
clazz = heading.multi? ? MultiTupleType : TupleType
|
37
|
+
clazz.new(heading)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # module RelBasedType
|
42
|
+
end # module Finitio
|