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.
Files changed (270) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +66 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +34 -30
  5. data/finitio.gemspec +1 -1
  6. data/lib/finitio.rb +7 -39
  7. data/lib/finitio/errors.rb +14 -0
  8. data/lib/finitio/support.rb +4 -1
  9. data/lib/finitio/support/attribute.rb +13 -7
  10. data/lib/finitio/support/compilation.rb +55 -0
  11. data/lib/finitio/support/constraint.rb +46 -0
  12. data/lib/finitio/support/contract.rb +33 -0
  13. data/lib/finitio/support/dress_helper.rb +3 -2
  14. data/lib/finitio/support/heading.rb +57 -17
  15. data/lib/finitio/support/metadata.rb +20 -0
  16. data/lib/finitio/support/type_factory.rb +154 -41
  17. data/lib/finitio/syntax.rb +16 -31
  18. data/lib/finitio/syntax/expr.rb +56 -0
  19. data/lib/finitio/syntax/expr/arith_op.rb +22 -0
  20. data/lib/finitio/syntax/expr/comparison.rb +22 -0
  21. data/lib/finitio/syntax/expr/fn_call.rb +24 -0
  22. data/lib/finitio/syntax/expr/identifier.rb +18 -0
  23. data/lib/finitio/syntax/expr/literal.rb +19 -0
  24. data/lib/finitio/syntax/expr/logic_dyadic.rb +22 -0
  25. data/lib/finitio/syntax/expr/logic_not.rb +21 -0
  26. data/lib/finitio/syntax/expr/oo_call.rb +24 -0
  27. data/lib/finitio/syntax/expr/parenthesized.rb +20 -0
  28. data/lib/finitio/syntax/expr/unary_minus_op.rb +21 -0
  29. data/lib/finitio/syntax/expressions.citrus +129 -0
  30. data/lib/finitio/syntax/finitio.citrus +10 -208
  31. data/lib/finitio/syntax/finitio.sexp +5 -1
  32. data/lib/finitio/syntax/lexer.citrus +91 -0
  33. data/lib/finitio/syntax/literal.rb +16 -0
  34. data/lib/finitio/syntax/literal/boolean.rb +22 -0
  35. data/lib/finitio/syntax/literal/integer.rb +14 -0
  36. data/lib/finitio/syntax/literal/real.rb +14 -0
  37. data/lib/finitio/syntax/literal/string.rb +14 -0
  38. data/lib/finitio/syntax/literals.citrus +44 -0
  39. data/lib/finitio/syntax/node.rb +53 -0
  40. data/lib/finitio/syntax/type.rb +28 -0
  41. data/lib/finitio/syntax/type/ad_type.rb +29 -0
  42. data/lib/finitio/syntax/{any_type.rb → type/any_type.rb} +1 -1
  43. data/lib/finitio/syntax/type/attribute.rb +33 -0
  44. data/lib/finitio/syntax/{builtin_type.rb → type/builtin_type.rb} +3 -1
  45. data/lib/finitio/syntax/{constraint_def.rb → type/constraint_def.rb} +4 -3
  46. data/lib/finitio/syntax/type/constraints.rb +17 -0
  47. data/lib/finitio/syntax/{contract.rb → type/contract.rb} +9 -3
  48. data/lib/finitio/syntax/{definitions.rb → type/definitions.rb} +1 -0
  49. data/lib/finitio/syntax/{expression.rb → type/expression.rb} +2 -1
  50. data/lib/finitio/syntax/{external_pair.rb → type/external_pair.rb} +3 -1
  51. data/lib/finitio/syntax/type/heading.rb +30 -0
  52. data/lib/finitio/syntax/{inline_pair.rb → type/inline_pair.rb} +3 -1
  53. data/lib/finitio/syntax/{lambda_expr.rb → type/lambda_expr.rb} +3 -0
  54. data/lib/finitio/syntax/type/main_type.rb +18 -0
  55. data/lib/finitio/syntax/type/metadata.rb +18 -0
  56. data/lib/finitio/syntax/type/metadata_attr.rb +15 -0
  57. data/lib/finitio/syntax/{named_constraint.rb → type/named_constraint.rb} +10 -3
  58. data/lib/finitio/syntax/type/relation_type.rb +24 -0
  59. data/lib/finitio/syntax/{seq_type.rb → type/seq_type.rb} +3 -0
  60. data/lib/finitio/syntax/{set_type.rb → type/set_type.rb} +3 -0
  61. data/lib/finitio/syntax/type/struct_type.rb +17 -0
  62. data/lib/finitio/syntax/{sub_type.rb → type/sub_type.rb} +3 -0
  63. data/lib/finitio/syntax/{system.rb → type/system.rb} +5 -4
  64. data/lib/finitio/syntax/type/tuple_type.rb +24 -0
  65. data/lib/finitio/syntax/{type_def.rb → type/type_def.rb} +8 -3
  66. data/lib/finitio/syntax/{type_ref.rb → type/type_ref.rb} +4 -1
  67. data/lib/finitio/syntax/{union_type.rb → type/union_type.rb} +1 -0
  68. data/lib/finitio/syntax/{unnamed_constraint.rb → type/unnamed_constraint.rb} +7 -1
  69. data/lib/finitio/syntax/types.citrus +196 -0
  70. data/lib/finitio/system.rb +15 -15
  71. data/lib/finitio/type.rb +38 -6
  72. data/lib/finitio/type/ad_type.rb +41 -18
  73. data/lib/finitio/type/alias_type.rb +37 -0
  74. data/lib/finitio/type/any_type.rb +7 -3
  75. data/lib/finitio/type/builtin_type.rb +5 -4
  76. data/lib/finitio/{support → type}/collection_type.rb +3 -4
  77. data/lib/finitio/type/hash_based_type.rb +91 -0
  78. data/lib/finitio/type/heading_based_type.rb +28 -0
  79. data/lib/finitio/type/multi_relation_type.rb +34 -0
  80. data/lib/finitio/type/multi_tuple_type.rb +29 -0
  81. data/lib/finitio/type/proxy_type.rb +40 -0
  82. data/lib/finitio/type/rel_based_type.rb +42 -0
  83. data/lib/finitio/type/relation_type.rb +6 -47
  84. data/lib/finitio/type/seq_type.rb +4 -0
  85. data/lib/finitio/type/set_type.rb +4 -0
  86. data/lib/finitio/type/struct_type.rb +84 -0
  87. data/lib/finitio/type/sub_type.rb +25 -22
  88. data/lib/finitio/type/tuple_type.rb +6 -57
  89. data/lib/finitio/type/union_type.rb +12 -5
  90. data/lib/finitio/version.rb +2 -2
  91. data/spec/{unit/attribute → attribute}/test_equality.rb +8 -5
  92. data/spec/{unit/attribute → attribute}/test_fetch_on.rb +5 -5
  93. data/spec/attribute/test_initialize.rb +26 -0
  94. data/spec/attribute/test_optional.rb +18 -0
  95. data/spec/attribute/test_required.rb +18 -0
  96. data/spec/attribute/test_to_name.rb +20 -0
  97. data/spec/constraint/test_anonymous.rb +20 -0
  98. data/spec/constraint/test_equality.rb +39 -0
  99. data/spec/constraint/test_name.rb +20 -0
  100. data/spec/constraint/test_named.rb +20 -0
  101. data/spec/constraint/test_triple_equal.rb +13 -0
  102. data/spec/{unit/qrb/system.q → finitio/system.fio} +0 -0
  103. data/spec/{unit/qrb → finitio}/test_ast.rb +0 -0
  104. data/spec/finitio/test_parse.rb +23 -0
  105. data/spec/{unit/qrb/test_parse.rb → finitio/test_system.rb} +6 -6
  106. data/spec/heading/test_allow_extra.rb +24 -0
  107. data/spec/{unit/heading → heading}/test_each.rb +2 -2
  108. data/spec/heading/test_equality.rb +38 -0
  109. data/spec/heading/test_hash.rb +38 -0
  110. data/spec/heading/test_hash_get.rb +17 -0
  111. data/spec/{unit/heading → heading}/test_initialize.rb +2 -2
  112. data/spec/heading/test_multi.rb +57 -0
  113. data/spec/{unit/heading → heading}/test_size.rb +0 -0
  114. data/spec/heading/test_to_name.rb +58 -0
  115. data/spec/spec_helper.rb +17 -1
  116. data/spec/syntax/expr/test_free_variables.rb +46 -0
  117. data/spec/syntax/expr/test_to_proc_source.rb +43 -0
  118. data/spec/{unit/syntax → syntax}/nodes/test_ad_type.rb +26 -26
  119. data/spec/{unit/syntax → syntax}/nodes/test_any_type.rb +2 -2
  120. data/spec/syntax/nodes/test_attribute.rb +65 -0
  121. data/spec/{unit/syntax → syntax}/nodes/test_builtin_type.rb +5 -5
  122. data/spec/{unit/syntax → syntax}/nodes/test_comment.rb +1 -1
  123. data/spec/{unit/syntax → syntax}/nodes/test_constraint_def.rb +3 -8
  124. data/spec/{unit/syntax → syntax}/nodes/test_constraints.rb +21 -16
  125. data/spec/{unit/syntax → syntax}/nodes/test_contract.rb +28 -35
  126. data/spec/{unit/syntax → syntax}/nodes/test_expression.rb +13 -5
  127. data/spec/{unit/syntax → syntax}/nodes/test_heading.rb +25 -7
  128. data/spec/syntax/nodes/test_metadata.rb +28 -0
  129. data/spec/{unit/syntax → syntax}/nodes/test_named_constraint.rb +8 -8
  130. data/spec/syntax/nodes/test_relation_type.rb +84 -0
  131. data/spec/{unit/syntax → syntax}/nodes/test_seq_type.rb +4 -4
  132. data/spec/{unit/syntax → syntax}/nodes/test_set_type.rb +4 -4
  133. data/spec/{unit/syntax → syntax}/nodes/test_spacing.rb +1 -1
  134. data/spec/syntax/nodes/test_struct_type.rb +38 -0
  135. data/spec/{unit/syntax → syntax}/nodes/test_sub_type.rb +14 -14
  136. data/spec/{unit/syntax → syntax}/nodes/test_system.rb +3 -3
  137. data/spec/syntax/nodes/test_tuple_type.rb +94 -0
  138. data/spec/syntax/nodes/test_type_def.rb +57 -0
  139. data/spec/{unit/syntax → syntax}/nodes/test_type_ref.rb +3 -3
  140. data/spec/{unit/syntax → syntax}/nodes/test_union_type.rb +3 -3
  141. data/spec/{unit/syntax → syntax}/nodes/test_unnamed_constraint.rb +7 -7
  142. data/spec/syntax/test_compile.rb +41 -0
  143. data/spec/{unit/syntax → syntax}/test_compile_type.rb +1 -1
  144. data/spec/{unit/system → system}/test_add_type.rb +6 -6
  145. data/spec/{unit/system → system}/test_dsl.rb +2 -2
  146. data/spec/{unit/system → system}/test_dup.rb +4 -4
  147. data/spec/{unit/system → system}/test_fetch.rb +4 -4
  148. data/spec/{unit/system → system}/test_get_type.rb +2 -2
  149. data/spec/{unit/system → system}/test_initialize.rb +0 -0
  150. data/spec/test_finitio.rb +8 -0
  151. data/spec/{unit/type → type}/ad_type/test_default_name.rb +1 -2
  152. data/spec/{unit/type → type}/ad_type/test_dress.rb +19 -9
  153. data/spec/{unit/type → type}/ad_type/test_include.rb +3 -3
  154. data/spec/{unit/type → type}/ad_type/test_initialize.rb +15 -8
  155. data/spec/{unit/type → type}/ad_type/test_name.rb +2 -2
  156. data/spec/type/alias_type/test_default_name.rb +10 -0
  157. data/spec/type/alias_type/test_delegation.rb +29 -0
  158. data/spec/type/alias_type/test_name.rb +10 -0
  159. data/spec/{unit/type → type}/any_type/test_default_name.rb +1 -1
  160. data/spec/{unit/type → type}/any_type/test_dress.rb +0 -0
  161. data/spec/{unit/type → type}/any_type/test_equality.rb +4 -4
  162. data/spec/{unit/type → type}/any_type/test_include.rb +2 -2
  163. data/spec/{unit/type → type}/any_type/test_initialize.rb +0 -0
  164. data/spec/{unit/type → type}/any_type/test_name.rb +2 -2
  165. data/spec/{unit/type → type}/builtin_type/test_default_name.rb +1 -1
  166. data/spec/{unit/type → type}/builtin_type/test_dress.rb +3 -3
  167. data/spec/{unit/type → type}/builtin_type/test_equality.rb +4 -4
  168. data/spec/{unit/type → type}/builtin_type/test_include.rb +2 -2
  169. data/spec/{unit/type → type}/builtin_type/test_initialize.rb +1 -1
  170. data/spec/{unit/type → type}/builtin_type/test_name.rb +2 -2
  171. data/spec/type/multi_relation_type/test_default_name.rb +19 -0
  172. data/spec/type/multi_relation_type/test_dress.rb +206 -0
  173. data/spec/type/multi_relation_type/test_equality.rb +36 -0
  174. data/spec/type/multi_relation_type/test_include.rb +89 -0
  175. data/spec/type/multi_relation_type/test_initialize.rb +29 -0
  176. data/spec/type/multi_relation_type/test_name.rb +27 -0
  177. data/spec/type/multi_tuple_type/test_default_name.rb +17 -0
  178. data/spec/type/multi_tuple_type/test_dress.rb +146 -0
  179. data/spec/type/multi_tuple_type/test_equality.rb +32 -0
  180. data/spec/type/multi_tuple_type/test_include.rb +73 -0
  181. data/spec/type/multi_tuple_type/test_initialize.rb +30 -0
  182. data/spec/type/multi_tuple_type/test_name.rb +24 -0
  183. data/spec/type/proxy_type/test_delegation.rb +37 -0
  184. data/spec/type/proxy_type/test_resolve.rb +29 -0
  185. data/spec/{unit/type → type}/relation_type/test_default_name.rb +0 -0
  186. data/spec/{unit/type → type}/relation_type/test_dress.rb +24 -24
  187. data/spec/{unit/type → type}/relation_type/test_equality.rb +6 -6
  188. data/spec/{unit/type → type}/relation_type/test_include.rb +4 -4
  189. data/spec/{unit/type → type}/relation_type/test_initialize.rb +2 -2
  190. data/spec/{unit/type → type}/relation_type/test_name.rb +0 -0
  191. data/spec/{unit/type → type}/seq_type/test_default_name.rb +0 -0
  192. data/spec/{unit/type → type}/seq_type/test_dress.rb +5 -5
  193. data/spec/{unit/type → type}/seq_type/test_equality.rb +4 -4
  194. data/spec/{unit/type → type}/seq_type/test_include.rb +4 -4
  195. data/spec/{unit/type → type}/seq_type/test_initialize.rb +3 -3
  196. data/spec/{unit/type → type}/seq_type/test_name.rb +0 -0
  197. data/spec/{unit/type → type}/set_type/test_default_name.rb +0 -0
  198. data/spec/{unit/type → type}/set_type/test_dress.rb +8 -8
  199. data/spec/{unit/type → type}/set_type/test_equality.rb +4 -4
  200. data/spec/{unit/type → type}/set_type/test_include.rb +4 -4
  201. data/spec/{unit/type → type}/set_type/test_initialize.rb +3 -3
  202. data/spec/{unit/type → type}/set_type/test_name.rb +0 -0
  203. data/spec/type/struct_type/test_default_name.rb +10 -0
  204. data/spec/type/struct_type/test_dress.rb +105 -0
  205. data/spec/type/struct_type/test_equality.rb +28 -0
  206. data/spec/type/struct_type/test_include.rb +40 -0
  207. data/spec/type/struct_type/test_initialize.rb +22 -0
  208. data/spec/type/struct_type/test_name.rb +20 -0
  209. data/spec/{unit/type → type}/sub_type/test_default_name.rb +2 -2
  210. data/spec/{unit/type → type}/sub_type/test_dress.rb +14 -14
  211. data/spec/type/sub_type/test_equality.rb +46 -0
  212. data/spec/{unit/type → type}/sub_type/test_include.rb +6 -6
  213. data/spec/type/sub_type/test_initialize.rb +13 -0
  214. data/spec/{unit/type → type}/sub_type/test_name.rb +4 -4
  215. data/spec/{unit/type → type}/tuple_type/test_default_name.rb +0 -0
  216. data/spec/{unit/type → type}/tuple_type/test_dress.rb +18 -18
  217. data/spec/{unit/type → type}/tuple_type/test_equality.rb +6 -6
  218. data/spec/{unit/type → type}/tuple_type/test_include.rb +4 -4
  219. data/spec/{unit/type → type}/tuple_type/test_initialize.rb +4 -4
  220. data/spec/{unit/type → type}/tuple_type/test_name.rb +0 -0
  221. data/spec/{unit/type → type}/union_type/test_default_name.rb +0 -0
  222. data/spec/{unit/type → type}/union_type/test_dress.rb +7 -6
  223. data/spec/{unit/type → type}/union_type/test_equality.rb +7 -7
  224. data/spec/{unit/type → type}/union_type/test_include.rb +3 -3
  225. data/spec/{unit/type → type}/union_type/test_initialize.rb +3 -3
  226. data/spec/{unit/type → type}/union_type/test_name.rb +0 -0
  227. data/spec/{unit/type_factory → type_factory}/dsl/test_adt.rb +4 -4
  228. data/spec/{unit/type_factory → type_factory}/dsl/test_any.rb +1 -1
  229. data/spec/{unit/type_factory → type_factory}/dsl/test_attribute.rb +16 -2
  230. data/spec/{unit/type_factory → type_factory}/dsl/test_attributes.rb +1 -1
  231. data/spec/{unit/type_factory → type_factory}/dsl/test_builtin.rb +3 -3
  232. data/spec/type_factory/dsl/test_multi_relation.rb +39 -0
  233. data/spec/type_factory/dsl/test_multi_tuple.rb +37 -0
  234. data/spec/{unit/type_factory → type_factory}/dsl/test_relation.rb +6 -6
  235. data/spec/{unit/type_factory → type_factory}/dsl/test_seq.rb +4 -4
  236. data/spec/{unit/type_factory → type_factory}/dsl/test_set.rb +4 -4
  237. data/spec/type_factory/dsl/test_struct.rb +45 -0
  238. data/spec/{unit/type_factory → type_factory}/dsl/test_subtype.rb +10 -8
  239. data/spec/{unit/type_factory → type_factory}/dsl/test_tuple.rb +5 -5
  240. data/spec/{unit/type_factory → type_factory}/dsl/test_union.rb +6 -6
  241. data/spec/{unit/type_factory → type_factory}/factory/test_builtin.rb +1 -1
  242. data/spec/{unit/type_factory → type_factory}/factory/test_seq_type.rb +2 -2
  243. data/spec/{unit/type_factory → type_factory}/factory/test_set_type.rb +2 -2
  244. data/spec/type_factory/factory/test_struct_type.rb +18 -0
  245. data/spec/{unit/type_factory → type_factory}/factory/test_sub_type.rb +7 -7
  246. data/spec/{unit/type_factory → type_factory}/factory/test_tuple_type.rb +4 -4
  247. metadata +398 -286
  248. data/lib/finitio/data_type.rb +0 -29
  249. data/lib/finitio/syntax/ad_type.rb +0 -32
  250. data/lib/finitio/syntax/attribute.rb +0 -15
  251. data/lib/finitio/syntax/constraints.rb +0 -22
  252. data/lib/finitio/syntax/heading.rb +0 -19
  253. data/lib/finitio/syntax/relation_type.rb +0 -15
  254. data/lib/finitio/syntax/support.rb +0 -13
  255. data/lib/finitio/syntax/tuple_type.rb +0 -15
  256. data/spec/acceptance/Finitio/test_default.rb +0 -96
  257. data/spec/acceptance/Finitio/test_parsing.rb +0 -15
  258. data/spec/acceptance/ad_type/test_in_finitio.rb +0 -82
  259. data/spec/acceptance/ad_type/test_in_ruby.rb +0 -60
  260. data/spec/unit/attribute/test_initialize.rb +0 -13
  261. data/spec/unit/attribute/test_to_name.rb +0 -10
  262. data/spec/unit/heading/test_equality.rb +0 -28
  263. data/spec/unit/heading/test_to_name.rb +0 -32
  264. data/spec/unit/syntax/nodes/test_attribute.rb +0 -38
  265. data/spec/unit/syntax/nodes/test_relation_type.rb +0 -59
  266. data/spec/unit/syntax/nodes/test_tuple_type.rb +0 -59
  267. data/spec/unit/syntax/nodes/test_type_def.rb +0 -33
  268. data/spec/unit/test_finitio.rb +0 -15
  269. data/spec/unit/type/sub_type/test_equality.rb +0 -34
  270. 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
- unless heading.is_a?(Heading)
28
- raise ArgumentError, "Heading expected, got `#{heading}`"
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
@@ -26,6 +26,10 @@ module Finitio
26
26
  class SeqType < Type
27
27
  include CollectionType
28
28
 
29
+ def representator
30
+ [elmType]
31
+ end
32
+
29
33
  def include?(value)
30
34
  value.is_a?(::Array) and value.all?{|v| elm_type.include?(v) }
31
35
  end
@@ -25,6 +25,10 @@ module Finitio
25
25
  class SetType < Type
26
26
  include CollectionType
27
27
 
28
+ def representator
29
+ [elmType].to_set
30
+ end
31
+
28
32
  def default_name
29
33
  "{#{elm_type.name}}"
30
34
  end
@@ -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
- DEFAULT_CONSTRAINT_NAMES = [:default, :predicate].freeze
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?(Hash)
38
- raise ArgumentError, "Hash expected for constraints, got #{constraints}"
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.keys.first.to_s.capitalize
54
+ constraints.first.name.to_s.capitalize
48
55
  end
49
56
 
50
57
  def include?(value)
51
- super_type.include?(value) && constraints.all?{|_,c| c===value }
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.each_pair do |name, constraint|
71
+ constraints.each do |constraint|
65
72
  next if constraint===uped
66
73
  msg = handler.default_error_message(self, value)
67
- msg << " (not #{name})" unless default_constraint?(name)
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
- return false unless other.is_a?(SubType)
77
- other.super_type == super_type and \
78
- set_equal?(constraints.values, other.constraints.values)
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.values)
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 BuiltinType
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
- unless heading.is_a?(Heading)
36
- raise ArgumentError, "Heading expected, got `#{heading}`"
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
- return false unless other.is_a?(UnionType)
69
- set_equal?(candidates, other.candidates)
74
+ super || (
75
+ other.is_a?(UnionType) && set_equal?(candidates, other.candidates)
76
+ )
70
77
  end
71
78
  alias :eql? :==
72
79
 
@@ -2,8 +2,8 @@ module Finitio
2
2
  module Version
3
3
 
4
4
  MAJOR = 0
5
- MINOR = 4
6
- TINY = 1
5
+ MINOR = 5
6
+ TINY = 0
7
7
 
8
8
  def self.to_s
9
9
  [ MAJOR, MINOR, TINY ].join('.')
@@ -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).should be_true
11
+ expect(attr1 == attr2).to eq(true)
11
12
  end
12
13
 
13
14
  it 'should distinguish different attributes' do
14
- (attr1 == attr3).should be_false
15
+ expect(attr1 == attr3).to eq(false)
16
+ expect(attr1 == attr4).to eq(false)
15
17
  end
16
18
 
17
- it 'should return nil if not equal' do
18
- (attr1 == 12).should be_nil
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.should eq(attr2.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
- }.should raise_error(ArgumentError, "Object responding to `fetch` expected")
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
- }.should raise_error(KeyError)
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" }.should eq("none")
45
+ expect(attr.fetch_on(arg){ "none" }).to eq("none")
46
46
  end
47
47
  end
48
48