finitio 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|