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