finitio 0.4.1 → 0.5.0

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