/src/tools/interpreter/liberty_interpreter_object_structure.e
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