PageRenderTime 18ms CodeModel.GetById 13ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/interpreter/liberty_interpreter_object_structure.e

http://github.com/tybor/Liberty
Specman e | 358 lines | 309 code | 32 blank | 17 comment | 13 complexity | f65bd630e2cdfea6244d254e2bf664bc MD5 | raw file
  1-- This file is part of Liberty Eiffel.
  2--
  3-- Liberty Eiffel is free software: you can redistribute it and/or modify
  4-- it under the terms of the GNU General Public License as published by
  5-- the Free Software Foundation, version 3 of the License.
  6--
  7-- Liberty Eiffel is distributed in the hope that it will be useful,
  8-- but WITHOUT ANY WARRANTY; without even the implied warranty of
  9-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 10-- GNU General Public License for more details.
 11--
 12-- You should have received a copy of the GNU General Public License
 13-- along with Liberty Eiffel.  If not, see <http://www.gnu.org/licenses/>.
 14--
 15class LIBERTY_INTERPRETER_OBJECT_STRUCTURE
 16
 17inherit
 18   LIBERTY_INTERPRETER_OBJECT
 19
 20creation {LIBERTY_INTERPRETER_OBJECT_CREATOR, LIBERTY_INTERPRETER_OBJECT_STRUCTURE}
 21   make
 22
 23creation {LIBERTY_INTERPRETER_OBJECT_STRUCTURE}
 24   with_attributes
 25
 26feature {ANY}
 27   type: LIBERTY_ACTUAL_TYPE
 28   hash_code: INTEGER
 29
 30   is_equal (other: LIBERTY_INTERPRETER_OBJECT): BOOLEAN is
 31      local
 32         is_equal_feature: LIBERTY_FEATURE_DEFINITION
 33         expanded_equal: LIBERTY_INTERPRETER_OBJECT_BOOLEAN
 34      do
 35         if other.is_void then
 36            -- Obviously this object is not Void.
 37         elseif type = other.type then
 38            if type.is_expanded then
 39               is_equal_feature := type.feature_definition(is_equal_feature_name)
 40               expanded_equal ::= interpreter.item_feature(Current, is_equal_feature, {FAST_ARRAY[LIBERTY_EXPRESSION] << other >> }, position)
 41               Result := expanded_equal.item
 42            else
 43               Result := Current = other
 44            end
 45         end
 46      end
 47
 48   converted_to (target_type: LIBERTY_ACTUAL_TYPE): LIBERTY_INTERPRETER_OBJECT is
 49      do
 50         not_yet_implemented
 51      end
 52
 53   put_attribute (a_attribute_name: FIXED_STRING; a_attribute: LIBERTY_INTERPRETER_OBJECT) is
 54      require
 55         a_attribute /= Void
 56      do
 57         attributes.put(a_attribute, a_attribute_name)
 58      ensure
 59         attribute_object(a_attribute_name) = a_attribute
 60      end
 61
 62   del_attribute (a_attribute_name: FIXED_STRING) is
 63      require
 64         a_attribute_name /= Void
 65      do
 66      ensure
 67         not has_attribute(a_attribute_name)
 68      end
 69
 70   has_attribute (a_attribute_name: FIXED_STRING): BOOLEAN is
 71      require
 72         a_attribute_name /= Void
 73      do
 74         Result := attributes.fast_has(a_attribute_name)
 75      end
 76
 77   attribute_object (a_attribute_name: FIXED_STRING): LIBERTY_INTERPRETER_OBJECT is
 78      require
 79         a_attribute_name /= Void
 80      do
 81         Result := attributes.fast_at(a_attribute_name)
 82      end
 83
 84feature {LIBERTY_INTERPRETER_EXTERNAL_TYPE_ANY_BUILTINS} -- Standard builtings
 85   builtin_is_equal (other: LIBERTY_INTERPRETER_OBJECT; a_position: LIBERTY_POSITION): BOOLEAN is
 86      local
 87         source: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
 88         i: INTEGER
 89      do
 90         if other.type /= type then
 91            interpreter.fatal_error("Type mismatch: expected " + type.full_name + ", but got " + other.type.full_name, a_position)
 92         else
 93            source ::= other
 94            Result := attributes.count = source.attributes.count
 95            from
 96               i := source.attributes.lower
 97            until
 98               not Result or else i > source.attributes.upper
 99            loop
100               -- That "and then" expression may look funny but it ensures that both structures have exactly
101               -- the same keys.
102               Result := attributes.item(i).is_equal(source.attributes.at(attributes.key(i)))
103                  and then source.attributes.item(i).is_equal(attributes.at(source.attributes.key(i)))
104               i := i + 1
105            end
106         end
107      end
108
109   builtin_standard_is_equal (other: LIBERTY_INTERPRETER_OBJECT; a_position: LIBERTY_POSITION): BOOLEAN is
110      do
111         Result := builtin_is_equal(other, a_position)
112      end
113
114   builtin_copy (other: LIBERTY_INTERPRETER_OBJECT; a_position: LIBERTY_POSITION) is
115      local
116         source: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
117         i: INTEGER; o: LIBERTY_INTERPRETER_OBJECT
118      do
119         if other.type /= type then
120            interpreter.fatal_error("Type mismatch: expected " + type.full_name + ", but got " + other.type.full_name, a_position)
121         else
122            source ::= other
123            attributes.clear_count
124            from
125               i := source.attributes.lower
126            until
127               i > source.attributes.upper
128            loop
129               o := source.attributes.item(i).as_right_value
130               attributes.put(o, source.attributes.key(i))
131               i := i + 1
132            end
133         end
134      end
135
136   builtin_twin (a_position: LIBERTY_POSITION): like Current is
137      local
138         copy_feature: LIBERTY_FEATURE_DEFINITION
139      do
140         Result ::= interpreter.new_object(type, a_position)
141         copy_feature := type.feature_definition(copy_feature_name)
142         interpreter.call_feature(Result, copy_feature, {FAST_ARRAY[LIBERTY_EXPRESSION] << Current >> }, a_position)
143      end
144
145   builtin_standard_copy (other: LIBERTY_INTERPRETER_OBJECT; a_position: LIBERTY_POSITION) is
146      do
147         builtin_copy(other, a_position)
148      end
149
150   builtin_standard_twin (a_position: LIBERTY_POSITION): like Current is
151      local
152         copy_feature: LIBERTY_FEATURE_DEFINITION
153      do
154         Result ::= interpreter.new_object(type, a_position)
155         copy_feature := type.feature_definition(standard_copy_feature_name)
156         interpreter.call_feature(Result, copy_feature, {FAST_ARRAY[LIBERTY_EXPRESSION] << Current >> }, a_position)
157      end
158
159feature {LIBERTY_INTERPRETER_OBJECT}
160   do_deep_twin (deep_twin_memory: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, LIBERTY_INTERPRETER_OBJECT]; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
161      local
162         i: INTEGER; o: LIBERTY_INTERPRETER_OBJECT
163         att: like attributes
164      do
165         Result := deep_twin_memory.reference_at(Current)
166         if Result = Void then
167            create {HASHED_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} att.with_capacity(attributes.capacity)
168            from
169               i := attributes.lower
170            until
171               i > attributes.upper
172            loop
173               o := attributes.item(i).do_deep_twin(deep_twin_memory, a_position)
174               att.put(o, attributes.key(i))
175               i := i + 1
176            end
177            create {LIBERTY_INTERPRETER_OBJECT_STRUCTURE} Result.with_attributes(interpreter, type, att, hash_code, a_position)
178            deep_twin_memory.put(Result, Current)
179         end
180      end
181
182   do_deep_equal (object: LIBERTY_INTERPRETER_OBJECT; deep_equal_memory: SET[LIBERTY_INTERPRETER_OBJECT]; a_position: LIBERTY_POSITION): BOOLEAN is
183      local
184         i: INTEGER; o: LIBERTY_INTERPRETER_OBJECT
185         compared: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
186      do
187         if deep_equal_memory.fast_has(Current) then
188            Result := True
189         elseif object.type /= type then
190            interpreter.fatal_error("Type mismatch: expected " + type.full_name + ", but got " + object.type.full_name, a_position)
191         elseif compared ?:= object then -- may be Void!
192            compared ::= object
193            Result := attributes.count = compared.attributes.count
194            from
195               i := attributes.lower
196            until
197               not Result or else i > attributes.upper
198            loop
199               o := compared.attributes.reference_at(attributes.key(i))
200               Result := o /= Void and then attributes.item(i).do_deep_equal(o, deep_equal_memory, a_position)
201               i := i + 1
202            end
203         end
204         deep_equal_memory.fast_add(Current)
205      end
206
207feature {LIBERTY_INTERPRETER_OBJECT_PRINTER, LIBERTY_INTERPRETER_FEATURE_CALL}
208   show_stack (o: OUTPUT_STREAM; indent: INTEGER) is
209      local
210         i: INTEGER
211      do
212         o.put_character('{')
213         o.put_string(type.full_name)
214         if not type.is_expanded then
215            o.put_character('@')
216            o.put_integer(hash_code)
217         end
218         if showing then
219            check
220               expanded_objects_cannot_be_recursively_referenced: not type.is_expanded
221            end
222         else
223            showing := True
224            o.put_line(once " [")
225            from
226               i := attributes.lower
227            until
228               i > attributes.upper
229            loop
230               interpreter.object_printer.put_indent(o, indent + 1)
231               o.put_string(attributes.key(i))
232               o.put_string(once " = ")
233               interpreter.object_printer.print_object(o, attributes.item(i), indent + 1)
234               i := i + 1
235            end
236            interpreter.object_printer.put_indent(o, indent)
237            o.put_string(once "] ")
238            showing := False
239         end
240         o.put_character('}')
241         o.put_new_line
242      end
243
244feature {}
245   showing: BOOLEAN
246
247   make (a_interpreter: like interpreter; a_type: like type; a_position: like position) is
248      require
249         a_interpreter /= Void
250         a_type /= Void
251         a_position /= Void
252      do
253         interpreter := a_interpreter
254         type := a_type
255         position := a_position
256         create {HASHED_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} attributes.with_capacity(2)
257         hash_code := new_hash_code
258      ensure
259         interpreter = a_interpreter
260         type = a_type
261         position = a_position
262      end
263
264   with_attributes (a_interpreter: like interpreter; a_type: like type; a_attributes: like attributes; a_hash_code: like hash_code; a_position: like position) is
265      require
266         a_interpreter /= Void
267         a_type /= Void
268         a_attributes /= Void
269         a_position /= Void
270      do
271         interpreter := a_interpreter
272         type := a_type
273         attributes := a_attributes
274         position := a_position
275         hash_code := a_hash_code
276      ensure
277         interpreter = a_interpreter
278         type = a_type
279         attributes = a_attributes
280         position = a_position
281         hash_code = a_hash_code
282      end
283
284feature {LIBERTY_INTERPRETER_OBJECT_STRUCTURE}
285   attributes: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]
286
287feature {}
288   expanded_is_equal (other: like Current): BOOLEAN is
289      require
290         other.type = type
291         type.is_expanded
292      local
293         i: INTEGER; name: FIXED_STRING
294      do
295         if attributes.count = other.attributes.count then
296            from
297               Result := True
298               i := attributes.lower
299            until
300               not Result or else i > attributes.upper
301            loop
302               name := attributes.key(i)
303               Result := other.attributes.fast_has(name) and then attributes.item(i).is_equal(other.attributes.fast_at(name))
304               i := i + 1
305            end
306         end
307      end
308
309   expanded_twin: like Current is
310      local
311         i: INTEGER; att: like attributes
312      do
313         create {HASHED_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} att.with_capacity(attributes.count)
314         from
315            i := attributes.lower
316         until
317            i > attributes.upper
318         loop
319            att.add(attributes.item(i).as_right_value, attributes.key(i))
320            i := i + 1
321         end
322         create Result.with_attributes(interpreter, type, att, hash_code, position)
323      end
324
325   copy_feature_name: LIBERTY_FEATURE_NAME is
326      once
327         create Result.make("copy".intern)
328      end
329
330   standard_copy_feature_name: LIBERTY_FEATURE_NAME is
331      once
332         create Result.make("standard_copy".intern)
333      end
334
335   is_equal_feature_name: LIBERTY_FEATURE_NAME is
336      once
337         create Result.make("is_equal".intern)
338      end
339
340   new_hash_code: INTEGER is
341      do
342         if type.is_expanded then
343            hash_code_producer.increment
344            Result := hash_code_producer.value
345         else
346            Result := to_pointer.hash_code
347         end
348      end
349
350   hash_code_producer: COUNTER is
351      once
352         create Result
353      end
354
355invariant
356   attributes /= Void
357
358end -- class LIBERTY_INTERPRETER_OBJECT_STRUCTURE