/src/tools/semantics/code/expressions/liberty_call_expression.e

http://github.com/tybor/Liberty · Specman e · 235 lines · 200 code · 21 blank · 14 comment · 14 complexity · ef354601df709ef447b0eda813196c44 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_CALL_EXPRESSION
  16. inherit
  17. LIBERTY_EXPRESSION
  18. redefine
  19. is_agent_call
  20. end
  21. LIBERTY_CALL
  22. create {LIBERTY_BUILDER_TOOLS, LIBERTY_CALL_EXPRESSION}
  23. make, implicit_current
  24. feature {ANY}
  25. target: LIBERTY_EXPRESSION
  26. entity: LIBERTY_FEATURE_ENTITY
  27. is_agent_call: BOOLEAN
  28. result_type: LIBERTY_TYPE is
  29. do
  30. Result := entity.result_type
  31. end
  32. feature {LIBERTY_REACHABLE, LIBERTY_REACHABLE_COLLECTION_MARKER}
  33. mark_reachable_code (mark: INTEGER) is
  34. do
  35. if target /= Void then
  36. target.mark_reachable_code(mark)
  37. end
  38. entity.mark_reachable_code(mark)
  39. expressions_marker.mark_reachable_code(mark, actuals)
  40. end
  41. feature {LIBERTY_AGENT, LIBERTY_CALL_EXPRESSION}
  42. set_agent_call is
  43. do
  44. is_agent_call := True
  45. ensure
  46. is_agent_call
  47. end
  48. set_open_target (open_target: LIBERTY_OPEN_ARGUMENT) is
  49. require
  50. is_agent_call
  51. {LIBERTY_OPEN_ARGUMENT} ?:= target
  52. open_target /= Void
  53. do
  54. target := open_target
  55. ensure
  56. target = open_target
  57. end
  58. set_actual (new_actual: LIBERTY_OPEN_ARGUMENT; index: INTEGER) is
  59. require
  60. is_agent_call
  61. actuals.valid_index(index)
  62. {LIBERTY_OPEN_ARGUMENT} ?:= actuals.item(index)
  63. new_actual /= Void
  64. do
  65. actuals_list.put(new_actual, index)
  66. ensure
  67. actuals.item(index) = new_actual
  68. end
  69. feature {LIBERTY_DELAYED_AGENT_CALL}
  70. can_compute_agent_type: BOOLEAN is
  71. local
  72. i: INTEGER
  73. do
  74. Result := entity.can_check_agent_signature(Current)
  75. if target /= Void then
  76. Result := target.is_open_argument implies target.result_type.is_known
  77. end
  78. if actuals /= Void then
  79. from
  80. i := actuals.lower
  81. until
  82. not Result or else i > actuals.upper
  83. loop
  84. Result := actuals.item(i).is_open_argument implies actuals.item(i).result_type.is_known
  85. i := i + 1
  86. end
  87. end
  88. end
  89. agent_type: LIBERTY_ACTUAL_TYPE is
  90. require
  91. is_agent_call
  92. can_compute_agent_type
  93. local
  94. arguments_types: COLLECTION[LIBERTY_KNOWN_TYPE]
  95. i: INTEGER
  96. do
  97. if actuals = Void and then (target = Void or else not target.is_open_argument) then
  98. arguments_types := entity.agent_signature(Current)
  99. else
  100. create {FAST_ARRAY[LIBERTY_KNOWN_TYPE]} arguments_types.with_capacity(actuals.count + 1)
  101. if target /= Void and then target.is_open_argument then
  102. arguments_types.add_last(target.result_type.known_type)
  103. end
  104. from
  105. i := actuals.lower
  106. until
  107. i > actuals.upper
  108. loop
  109. if actuals.item(i).is_open_argument then
  110. arguments_types.add_last(actuals.item(i).result_type.known_type)
  111. end
  112. i := i + 1
  113. end
  114. end
  115. entity.check_agent_signature(Current)
  116. if result_type = Void then
  117. Result := lookup.universe.type_procedure(arguments_types, position)
  118. elseif result_type = lookup.universe.type_boolean then
  119. Result := lookup.universe.type_predicate(arguments_types, position)
  120. else
  121. Result := lookup.universe.type_function(arguments_types, result_type.known_type, position)
  122. end
  123. end
  124. feature {LIBERTY_DELAYED_OPEN_ARGUMENT}
  125. can_compute_open_argument_type (index: INTEGER): BOOLEAN is
  126. do
  127. if index = -1 then
  128. Result := entity.can_check_agent_signature(Current) and then target.result_type.is_known
  129. elseif actuals /= Void then
  130. check
  131. actuals.valid_index(index)
  132. end
  133. Result := entity.can_check_agent_signature(Current) and then actuals.item(index).result_type.is_known
  134. end
  135. end
  136. open_argument_type (index: INTEGER): LIBERTY_KNOWN_TYPE is
  137. require
  138. can_compute_open_argument_type(index)
  139. do
  140. if index = -1 then
  141. Result := target.result_type.known_type
  142. elseif actuals /= Void then
  143. Result := actuals.item(index).result_type.known_type
  144. end
  145. end
  146. feature {}
  147. make (a_target: like target; a_entity: like entity; a_actuals: like actuals_list; a_position: like position) is
  148. require
  149. a_target /= Void
  150. a_entity /= Void
  151. a_actuals /= Void
  152. a_position /= Void
  153. do
  154. target := a_target
  155. entity := a_entity
  156. actuals_list := a_actuals
  157. position := a_position
  158. register_for_promotion
  159. ensure
  160. target = a_target or else {LIBERTY_CAST_EXPRESSION} ?:= target
  161. entity = a_entity
  162. actuals_list = a_actuals
  163. position = a_position
  164. end
  165. implicit_current (a_entity: like entity; a_actuals: like actuals_list; a_position: like position) is
  166. require
  167. a_entity /= Void
  168. a_actuals /= Void
  169. a_position /= Void
  170. do
  171. entity := a_entity
  172. actuals_list := a_actuals
  173. position := a_position
  174. ensure
  175. is_implicit_current
  176. entity = a_entity
  177. actuals_list = a_actuals
  178. position = a_position
  179. end
  180. lookup: LIBERTY_TYPE_LOOKUP
  181. actuals_list: COLLECTION[LIBERTY_EXPRESSION]
  182. no_args: COLLECTION[LIBERTY_KNOWN_TYPE] is
  183. once
  184. create {FAST_ARRAY[LIBERTY_KNOWN_TYPE]} Result.with_capacity(0)
  185. end
  186. make_new (a_target: like target; a_entity: like entity; a_actuals: like actuals_list; a_position: like position): like Current is
  187. do
  188. if a_target = Void then
  189. create Result.implicit_current(a_entity, a_actuals, a_position)
  190. else
  191. create Result.make(a_target, a_entity, a_actuals, a_position)
  192. end
  193. if is_agent_call then
  194. Result.set_agent_call
  195. end
  196. end
  197. feature {LIBERTY_CALL_PROMOTION}
  198. set_entity (a_entity: like entity) is
  199. do
  200. entity := a_entity
  201. end
  202. set_target (a_target: like target) is
  203. do
  204. target := a_target
  205. end
  206. feature {ANY}
  207. accept (v: VISITOR) is
  208. local
  209. v0: LIBERTY_CALL_EXPRESSION_VISITOR
  210. do
  211. v0 ::= v
  212. v0.visit_liberty_call_expression(Current)
  213. end
  214. end