PageRenderTime 9ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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