1 # $Id: map.rb,v 1.6 2012/04/17 02:49:40 machan Exp $
2
3 require 'tmdoc/tmstd/assertion'
4 require 'tmdoc/tmstd/lsm/abstraction'
5
6
7 module TmStd
8
9 module Lsm
10
11 module Collection
12
13 module Map
14
15 class Abstract < Collection::Abstract
16 attr_reader :lsm_elements
17 alias to_hash lsm_elements
18
19
20 def initialize(elements = {}, &block)
21 Assertion.kind_of elements, Hash
22
23 __domain_class__
24 __range_class__
25
26 @lsm_elements = Hash.new(&block)
27
28 for domain, range in elements
29 __update__! domain, range
30 end
31 end
32
33
34 def each(&block)
35 self.lsm_elements.each(&block)
36
37 nil
38 end
39
40
41 def any?(&block)
42 Assertion.boolean self.ranges.any?(&block)
43 end
44
45
46 def domains
47 Assertion.kind_of self.lsm_elements.keys, Array
48 end
49
50
51 def ranges
52 Assertion.kind_of self.lsm_elements.values, Array
53 end
54
55
56 def include?(domain)
57 Assertion.kind_of domain, __domain_class__
58
59 result = if self.lsm_elements[domain] then true else false end
60
61 Assertion.boolean result
62 end
63
64
65 def at(dom)
66 Assertion.kind_of dom, __domain_class__
67
68 Assertion.opt_kind_of self.lsm_elements[dom], __range_class__
69 end
70
71
72 def update(dom, ran, &block)
73 Assertion.kind_of dom, __domain_class__
74 Assertion.kind_of ran, __range_class__
75
76 new_map = self.class.new self.lsm_elements
77 new_map.__update__!(dom, ran, &block)
78
79 new_map
80 end
81
82
83 def __update__!(dom, self_ran, &block)
84 Assertion.kind_of dom, __domain_class__
85 Assertion.kind_of self_ran, __range_class__
86
87 other_ran = self.at dom
88 ran =
89 if other_ran
90 if block
91 block.call(dom, self_ran, other_ran)
92 else
93 Assertion.abort(
94 "Index Error, dom: %s, self_ran: %s, other_ran: %s",
95 dom.to_s, self_ran.to_s, other_ran.to_s
96 )
97 end
98 else
99 self_ran
100 end
101 Assertion.kind_of ran, __range_class__
102
103 case dom
104 when ::String, ::Symbol, ::Integer
105 dom.freeze
106 else
107 dom.freeze_equality!
108 end
109 self.lsm_elements[dom] = ran
110
111 nil
112 end
113
114
115 def merge(other, &block)
116 Assertion.kind_of other, self.class
117
118 new_map = self.class.new self.lsm_elements
119 new_map.__merge__!(other, &block)
120
121 Assertion.kind_of new_map, Abstract
122 end
123 alias + merge
124
125
126 def __merge__!(other, &block)
127 Assertion.kind_of other, self.class
128
129 self.lsm_elements.merge!(other.lsm_elements) {
130 |dom, self_ran, other_ran|
131
132 if block
133 block.call(dom, self_ran, other_ran)
134 else
135 Assertion.abort(
136 "Index Error, Dom: %s, Self-Ran: %s, Other-Ran: %s",
137 dom.to_s, self_ran.to_s, other_ran.to_s
138 )
139 end
140 }
141
142 nil
143 end
144
145
146 def __domain_class__
147 elem_class = lsm_element_class 'LSM_DOMAIN_CLASS'
148
149 Assertion.kind_of elem_class, ::Class
150 end
151
152
153
154 def __range_class__
155 elem_class = lsm_element_class 'LSM_RANGE_CLASS'
156
157 Assertion.kind_of elem_class, ::Class
158 end
159 end
160
161
162
163 module Mutable
164 def update!(domain, range)
165 self.__update__! domain, range
166
167 nil
168 end
169
170
171 def merge!(other, &block)
172 self.__merge__! other, &block
173
174 nil
175 end
176 end
177
178 end # TmStd::Lsm::Collection::Map
179
180 end # TmStd::Lsm::Collection
181
182 end # TmStd::Lsm
183
184 end # TmStd