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
@@ -22,60 +22,19 @@ module Finitio
|
|
22
22
|
# dress :: Object -> Set[Hash[...]] throws TypeError
|
23
23
|
#
|
24
24
|
class RelationType < Type
|
25
|
+
include HeadingBasedType
|
26
|
+
include RelBasedType
|
25
27
|
|
26
|
-
def initialize(heading, name = nil)
|
27
|
-
|
28
|
-
|
28
|
+
def initialize(heading, name = nil, metadata = nil)
|
29
|
+
super
|
30
|
+
if heading.multi?
|
31
|
+
raise ArgumentError, "Multi heading forbidden"
|
29
32
|
end
|
30
|
-
|
31
|
-
super(name)
|
32
|
-
@heading = heading
|
33
33
|
end
|
34
|
-
attr_reader :heading
|
35
34
|
|
36
35
|
def default_name
|
37
36
|
"{{#{heading.to_name}}}"
|
38
37
|
end
|
39
38
|
|
40
|
-
def include?(value)
|
41
|
-
value.is_a?(Set) && value.all?{|tuple|
|
42
|
-
tuple_type.include?(tuple)
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
# Apply the corresponding TupleType's `dress` to every element of `value`
|
47
|
-
# (any enumerable). Return a Set of transformed tuples. Fail if anything
|
48
|
-
# goes wrong transforming tuples or if duplicates are found.
|
49
|
-
def dress(value, handler = DressHelper.new)
|
50
|
-
handler.failed!(self, value) unless value.respond_to?(:each)
|
51
|
-
|
52
|
-
# Up every tuple and keep results in a Set
|
53
|
-
set = Set.new
|
54
|
-
handler.iterate(value) do |tuple, index|
|
55
|
-
tuple = tuple_type.dress(tuple, handler)
|
56
|
-
handler.fail!("Duplicate tuple") if set.include?(tuple)
|
57
|
-
set << tuple
|
58
|
-
end
|
59
|
-
|
60
|
-
# Return built tuples
|
61
|
-
set
|
62
|
-
end
|
63
|
-
|
64
|
-
def ==(other)
|
65
|
-
return false unless other.is_a?(RelationType)
|
66
|
-
heading == other.heading
|
67
|
-
end
|
68
|
-
alias :eql? :==
|
69
|
-
|
70
|
-
def hash
|
71
|
-
self.class.hash ^ heading.hash
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def tuple_type
|
77
|
-
@tuple_type ||= TupleType.new(heading)
|
78
|
-
end
|
79
|
-
|
80
39
|
end # class RelationType
|
81
40
|
end # module Finitio
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Finitio
|
2
|
+
#
|
3
|
+
# The Struct type generator allows capturing positional sequences of values,
|
4
|
+
# such as pairs, triples and so forth. For instance, a Point type could be
|
5
|
+
# defined as follows:
|
6
|
+
#
|
7
|
+
# Point = <Length, Angle>
|
8
|
+
#
|
9
|
+
# This class allows capturing those information types, as in:
|
10
|
+
#
|
11
|
+
# Length = BuiltinType.new(Fixnum)
|
12
|
+
# Angle = BuiltinType.new(Float)
|
13
|
+
# Point = StructType.new([Length, Angle])
|
14
|
+
#
|
15
|
+
# A simple Array is used as concrete ruby representation for structs. The
|
16
|
+
# values map to the concrete representations of each component type:
|
17
|
+
#
|
18
|
+
# R(Point) = Array[R(Length) ^ R(Angle)]
|
19
|
+
# = Array[Fixnum ^ Float]
|
20
|
+
# = Array[Numeric]
|
21
|
+
#
|
22
|
+
# where `^` denotes the `least common super type` operator on ruby classes.
|
23
|
+
#
|
24
|
+
# Accordingly, the `dress` transformation function has the signature below.
|
25
|
+
# It expects it's Alpha/Object argument to be an Array with all and only the
|
26
|
+
# expected components. The `dress` function applies on every component
|
27
|
+
# according to its type.
|
28
|
+
#
|
29
|
+
# dress :: Alpha -> Point throws TypeError
|
30
|
+
# dress :: Object -> Array[Numeric] throws TypeError
|
31
|
+
#
|
32
|
+
class StructType < Type
|
33
|
+
|
34
|
+
def initialize(component_types, name = nil, metadata = nil)
|
35
|
+
unless component_types.is_a?(Array) &&
|
36
|
+
component_types.all?{|c| c.is_a?(Type) }
|
37
|
+
raise ArgumentError, "[Finitio::Type] expected, got `#{component_types}`"
|
38
|
+
end
|
39
|
+
|
40
|
+
super(name, metadata)
|
41
|
+
@component_types = component_types
|
42
|
+
end
|
43
|
+
attr_reader :component_types
|
44
|
+
|
45
|
+
def representator
|
46
|
+
component_types.map(&:representator)
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_name
|
50
|
+
"<" + @component_types.map(&:name).join(', ') + ">"
|
51
|
+
end
|
52
|
+
|
53
|
+
def include?(value)
|
54
|
+
value.is_a?(Array) &&
|
55
|
+
value.size==component_types.size &&
|
56
|
+
value.zip(component_types).all?{|v,t| t.include?(v) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def dress(value, handler = DressHelper.new)
|
60
|
+
handler.failed!(self, value) unless value.is_a?(Array)
|
61
|
+
|
62
|
+
# check the size
|
63
|
+
cs, vs = component_types.size, value.size
|
64
|
+
handler.fail!("Struct size mismatch (#{vs} for #{cs})") unless cs==vs
|
65
|
+
|
66
|
+
# dress components
|
67
|
+
array = []
|
68
|
+
handler.iterate(value) do |elm, index|
|
69
|
+
array << component_types[index].dress(elm, handler)
|
70
|
+
end
|
71
|
+
array
|
72
|
+
end
|
73
|
+
|
74
|
+
def ==(other)
|
75
|
+
super || (other.is_a?(StructType) && other.component_types == component_types)
|
76
|
+
end
|
77
|
+
alias :eql? :==
|
78
|
+
|
79
|
+
def hash
|
80
|
+
self.class.hash ^ component_types.hash
|
81
|
+
end
|
82
|
+
|
83
|
+
end # class StructType
|
84
|
+
end # module Finitio
|
@@ -27,28 +27,35 @@ module Finitio
|
|
27
27
|
#
|
28
28
|
class SubType < Type
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
def initialize(super_type, constraints, name = nil)
|
30
|
+
def initialize(super_type, constraints, name = nil, metadata = nil)
|
33
31
|
unless super_type.is_a?(Type)
|
34
32
|
raise ArgumentError, "Finitio::Type expected, got #{super_type}"
|
35
33
|
end
|
36
34
|
|
37
|
-
unless constraints.is_a?(
|
38
|
-
|
35
|
+
unless constraints.is_a?(Array) &&
|
36
|
+
constraints.all?{|v| v.is_a?(Constraint) }
|
37
|
+
raise ArgumentError, "[Constraint] expected for constraints, got #{constraints}"
|
39
38
|
end
|
40
39
|
|
41
|
-
super(name)
|
40
|
+
super(name, metadata)
|
42
41
|
@super_type, @constraints = super_type, constraints.freeze
|
43
42
|
end
|
44
43
|
attr_reader :super_type, :constraints
|
45
44
|
|
45
|
+
def representator
|
46
|
+
super_type.representator
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](name)
|
50
|
+
constraints.find{|c| c.name == name }
|
51
|
+
end
|
52
|
+
|
46
53
|
def default_name
|
47
|
-
constraints.
|
54
|
+
constraints.first.name.to_s.capitalize
|
48
55
|
end
|
49
56
|
|
50
57
|
def include?(value)
|
51
|
-
super_type.include?(value) && constraints.all?{|
|
58
|
+
super_type.include?(value) && constraints.all?{|c| c===value }
|
52
59
|
end
|
53
60
|
|
54
61
|
# Check that `value` can be uped through the supertype, then verify all
|
@@ -61,10 +68,12 @@ module Finitio
|
|
61
68
|
end
|
62
69
|
|
63
70
|
# Check each constraint in turn
|
64
|
-
constraints.
|
71
|
+
constraints.each do |constraint|
|
65
72
|
next if constraint===uped
|
66
73
|
msg = handler.default_error_message(self, value)
|
67
|
-
|
74
|
+
if constraint.named? && constraints.size>1
|
75
|
+
msg << " (not #{constraint.name})"
|
76
|
+
end
|
68
77
|
handler.fail!(msg)
|
69
78
|
end
|
70
79
|
|
@@ -73,22 +82,16 @@ module Finitio
|
|
73
82
|
end
|
74
83
|
|
75
84
|
def ==(other)
|
76
|
-
|
77
|
-
|
78
|
-
|
85
|
+
super || (
|
86
|
+
other.is_a?(SubType) && (other.super_type == super_type) &&
|
87
|
+
set_equal?(constraints, other.constraints)
|
88
|
+
)
|
79
89
|
end
|
80
90
|
alias :eql? :==
|
81
91
|
|
82
92
|
def hash
|
83
|
-
self.class.hash ^ super_type.hash ^ set_hash(constraints
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
def default_constraint?(name)
|
89
|
-
DEFAULT_CONSTRAINT_NAMES.include?(name) or \
|
90
|
-
name.to_s.capitalize == self.name
|
93
|
+
self.class.hash ^ super_type.hash ^ set_hash(constraints)
|
91
94
|
end
|
92
95
|
|
93
|
-
end # class
|
96
|
+
end # class SubType
|
94
97
|
end # module Finitio
|
@@ -30,70 +30,19 @@ module Finitio
|
|
30
30
|
# dress :: Object -> Hash[r: Fixnum, theta: Float] throws TypeError
|
31
31
|
#
|
32
32
|
class TupleType < Type
|
33
|
+
include HeadingBasedType
|
34
|
+
include HashBasedType
|
33
35
|
|
34
|
-
def initialize(heading, name = nil)
|
35
|
-
|
36
|
-
|
36
|
+
def initialize(heading, name = nil, metadata = nil)
|
37
|
+
super
|
38
|
+
if heading.multi?
|
39
|
+
raise ArgumentError, "Multi heading forbidden"
|
37
40
|
end
|
38
|
-
|
39
|
-
super(name)
|
40
|
-
@heading = heading
|
41
41
|
end
|
42
|
-
attr_reader :heading
|
43
42
|
|
44
43
|
def default_name
|
45
44
|
"{#{heading.to_name}}"
|
46
45
|
end
|
47
46
|
|
48
|
-
def include?(value)
|
49
|
-
return false unless value.is_a?(Hash)
|
50
|
-
return false if value.size > heading.size
|
51
|
-
heading.all? do |attribute|
|
52
|
-
attr_val = value.fetch(attribute.name){
|
53
|
-
return false
|
54
|
-
}
|
55
|
-
attribute.type.include?(attr_val)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Convert `value` (supposed to be Hash) to a Tuple, by checking attributes
|
60
|
-
# and applying `dress` on them in turn. Raise an error if any attribute
|
61
|
-
# is missing or unrecognized, as well as if any sub transformation fails.
|
62
|
-
def dress(value, handler = DressHelper.new)
|
63
|
-
handler.failed!(self, value) unless value.is_a?(Hash)
|
64
|
-
|
65
|
-
# Uped values, i.e. tuple under construction
|
66
|
-
uped = {}
|
67
|
-
|
68
|
-
# Check the tuple arity and fail fast if extra attributes
|
69
|
-
# (missing attributes are handled just after)
|
70
|
-
if value.size > heading.size
|
71
|
-
extra = value.keys.map(&:to_s) - heading.map{|attr| attr.name.to_s }
|
72
|
-
handler.fail!("Unrecognized attribute `#{extra.first}`")
|
73
|
-
end
|
74
|
-
|
75
|
-
# Up each attribute in turn now. Fail on missing ones.
|
76
|
-
heading.each do |attribute|
|
77
|
-
val = attribute.fetch_on(value) do
|
78
|
-
handler.fail!("Missing attribute `#{attribute.name}`")
|
79
|
-
end
|
80
|
-
handler.deeper(attribute.name) do
|
81
|
-
uped[attribute.name] = attribute.type.dress(val, handler)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
uped
|
86
|
-
end
|
87
|
-
|
88
|
-
def ==(other)
|
89
|
-
return false unless other.is_a?(TupleType)
|
90
|
-
heading == other.heading
|
91
|
-
end
|
92
|
-
alias :eql? :==
|
93
|
-
|
94
|
-
def hash
|
95
|
-
self.class.hash ^ heading.hash
|
96
|
-
end
|
97
|
-
|
98
47
|
end # class TupleType
|
99
48
|
end # module Finitio
|
@@ -29,16 +29,20 @@ module Finitio
|
|
29
29
|
#
|
30
30
|
class UnionType < Type
|
31
31
|
|
32
|
-
def initialize(candidates, name = nil)
|
32
|
+
def initialize(candidates, name = nil, metadata = nil)
|
33
33
|
unless candidates.all?{|c| c.is_a?(Type) }
|
34
34
|
raise ArgumentError, "[Finitio::Type] expected, got #{candidates}"
|
35
35
|
end
|
36
36
|
|
37
|
-
super(name)
|
37
|
+
super(name, metadata)
|
38
38
|
@candidates = candidates.freeze
|
39
39
|
end
|
40
40
|
attr_reader :candidates
|
41
41
|
|
42
|
+
def representator
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
42
46
|
def include?(value)
|
43
47
|
candidates.any?{|c| c.include?(value) }
|
44
48
|
end
|
@@ -47,6 +51,7 @@ module Finitio
|
|
47
51
|
# returned by the first one that does not fail. Fail with an TypeError if no
|
48
52
|
# candidate succeeds at tranforming `value`.
|
49
53
|
def dress(value, handler = DressHelper.new)
|
54
|
+
error = nil
|
50
55
|
|
51
56
|
# Do nothing on TypeError as the next candidate could be the good one!
|
52
57
|
candidates.each do |c|
|
@@ -54,10 +59,11 @@ module Finitio
|
|
54
59
|
c.dress(value, handler)
|
55
60
|
end
|
56
61
|
return uped if success
|
62
|
+
error ||= uped
|
57
63
|
end
|
58
64
|
|
59
65
|
# No one succeed, just fail
|
60
|
-
handler.failed!(self, value)
|
66
|
+
handler.failed!(self, value, error)
|
61
67
|
end
|
62
68
|
|
63
69
|
def default_name
|
@@ -65,8 +71,9 @@ module Finitio
|
|
65
71
|
end
|
66
72
|
|
67
73
|
def ==(other)
|
68
|
-
|
69
|
-
|
74
|
+
super || (
|
75
|
+
other.is_a?(UnionType) && set_equal?(candidates, other.candidates)
|
76
|
+
)
|
70
77
|
end
|
71
78
|
alias :eql? :==
|
72
79
|
|
data/lib/finitio/version.rb
CHANGED
@@ -5,21 +5,24 @@ module Finitio
|
|
5
5
|
let(:attr1){ Attribute.new(:red, intType) }
|
6
6
|
let(:attr2){ Attribute.new(:red, intType) }
|
7
7
|
let(:attr3){ Attribute.new(:blue, intType) }
|
8
|
+
let(:attr4){ Attribute.new(:red, intType, false) }
|
8
9
|
|
9
10
|
it 'should apply structural equality' do
|
10
|
-
(attr1 == attr2).
|
11
|
+
expect(attr1 == attr2).to eq(true)
|
11
12
|
end
|
12
13
|
|
13
14
|
it 'should distinguish different attributes' do
|
14
|
-
(attr1 == attr3).
|
15
|
+
expect(attr1 == attr3).to eq(false)
|
16
|
+
expect(attr1 == attr4).to eq(false)
|
15
17
|
end
|
16
18
|
|
17
|
-
it 'should
|
18
|
-
(attr1 == 12).
|
19
|
+
it 'should false against non Attribute' do
|
20
|
+
expect(attr1 == 12).to eq(false)
|
19
21
|
end
|
20
22
|
|
21
23
|
it 'should implement hash accordingly' do
|
22
|
-
attr1.hash.
|
24
|
+
expect(attr1.hash).to eq(attr2.hash)
|
25
|
+
expect(attr1.hash).not_to eq(attr4.hash)
|
23
26
|
end
|
24
27
|
|
25
28
|
end
|
@@ -10,9 +10,9 @@ module Finitio
|
|
10
10
|
let(:arg){ 12 }
|
11
11
|
|
12
12
|
it 'should raise an error' do
|
13
|
-
|
13
|
+
expect{
|
14
14
|
subject
|
15
|
-
}.
|
15
|
+
}.to raise_error(ArgumentError, "Object responding to `fetch` expected")
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -32,9 +32,9 @@ module Finitio
|
|
32
32
|
let(:arg){ { other: 123 } }
|
33
33
|
|
34
34
|
it 'should raise an error' do
|
35
|
-
|
35
|
+
expect{
|
36
36
|
attr.fetch_on(arg)
|
37
|
-
}.
|
37
|
+
}.to raise_error(KeyError)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -42,7 +42,7 @@ module Finitio
|
|
42
42
|
let(:arg){ { other: 123 } }
|
43
43
|
|
44
44
|
it 'should yield the block' do
|
45
|
-
attr.fetch_on(arg){ "none" }.
|
45
|
+
expect(attr.fetch_on(arg){ "none" }).to eq("none")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|