PageRenderTime 34ms CodeModel.GetById 14ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 1ms

/src/tools/semantics/code/entities/liberty_feature_definition.e

http://github.com/tybor/Liberty
Specman e | 524 lines | 460 code | 46 blank | 18 comment | 32 complexity | fae24fb6c7b034fafd198aa7c37c200b 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_FEATURE_DEFINITION
 16
 17inherit
 18   LIBERTY_ENTITY
 19      redefine copy, out_in_tagged_out_memory
 20      end
 21
 22insert
 23   LIBERTY_REACHABLE_MARKED
 24      redefine
 25         copy, out_in_tagged_out_memory
 26      end
 27   LOGGING
 28      redefine
 29         copy, out_in_tagged_out_memory
 30      end
 31
 32creation {LIBERTY_BUILDER_TOOLS}
 33   make
 34
 35creation {LIBERTY_FEATURE_DEFINITION}
 36   specialized
 37
 38feature {ANY}
 39   feature_name: LIBERTY_FEATURE_NAME
 40   creation_clients: COLLECTION[LIBERTY_TYPE]
 41   clients: COLLECTION[LIBERTY_TYPE]
 42
 43   is_frozen: BOOLEAN
 44   the_feature: LIBERTY_FEATURE
 45
 46   current_type: LIBERTY_ACTUAL_TYPE
 47
 48   out_in_tagged_out_memory is
 49      do
 50         tagged_out_memory.append(once "feature definition: ")
 51         feature_name.out_in_tagged_out_memory
 52      end
 53
 54   name: FIXED_STRING is
 55      do
 56         Result := feature_name.name
 57      end
 58
 59   is_regular: BOOLEAN is
 60      do
 61         Result := feature_name.is_regular
 62      end
 63
 64   is_prefix: BOOLEAN is
 65      do
 66         Result := feature_name.is_prefix
 67      end
 68
 69   is_infix: BOOLEAN is
 70      do
 71         Result := feature_name.is_infix
 72      end
 73
 74   is_creation: BOOLEAN is
 75      do
 76         Result := creation_clients /= Void
 77      end
 78
 79   result_type: LIBERTY_TYPE is
 80      do
 81         if the_feature /= Void then
 82            Result := the_feature.result_type
 83         else
 84            -- should not happen??
 85            not_yet_implemented
 86         end
 87      end
 88
 89   copy (other: like Current) is
 90      do
 91         feature_name := other.feature_name
 92         current_type := other.current_type
 93         clients := other.clients.twin
 94         is_frozen := other.is_frozen
 95         the_feature := other.the_feature
 96      end
 97
 98   specialized_in (a_type: LIBERTY_ACTUAL_TYPE): like Current is
 99      local
100         cl, ccl: COLLECTION[LIBERTY_TYPE]
101         f, pf: like the_feature
102         p: like precursors
103         i: INTEGER
104      do
105         debug ("feature.specialization")
106            log.trace.put_string(once "Specializing in ")
107            log.trace.put_string(a_type.full_name)
108            debug_display(log.trace, False)
109         end
110         cl := specialized_clients(clients, a_type)
111         if creation_clients /= Void then
112            ccl := specialized_clients(creation_clients, a_type)
113         end
114         if the_feature /= Void then
115            f := the_feature.specialized_in(a_type)
116         end
117         p := precursors
118         if p /= Void then
119            from
120               i := p.lower
121            until
122               i > p.upper
123            loop
124               pf := p.item(i).specialized_in(a_type)
125               if pf /= p.item(i) then
126                  if p = precursors then
127                     p := p.twin
128                  end
129                  p.fast_put(pf, p.key(i))
130               end
131               i := i + 1
132            end
133         end
134         if a_type = current_type and then cl = clients and then ccl = creation_clients and then f = the_feature and then p = precursors then
135            Result := Current
136         else
137            create Result.specialized(feature_name, f.current_type, ccl, cl, is_frozen, f, p, position)
138         end
139         debug ("feature.specialization")
140            log.trace.put_string(once "Specialized in ")
141            log.trace.put_string(a_type.full_name)
142            log.trace.put_string(once ": ")
143            Result.debug_display(log.trace, True)
144         end
145      end
146
147feature {}
148   specialized_clients (a_clients: like clients; a_type: LIBERTY_ACTUAL_TYPE): like clients is
149      require
150         a_type /= Void
151         a_clients /= Void
152      local
153         t: LIBERTY_TYPE
154         i: INTEGER
155      do
156         from
157            Result := a_clients
158            i := Result.lower
159         until
160            i > Result.upper
161         loop
162            t := Result.item(i).specialized_in(a_type)
163            if t /= Result.item(i) then
164               if Result = a_clients then
165                  Result := Result.twin
166               end
167               Result.put(t, i)
168            end
169            i := i + 1
170         end
171      end
172
173feature {LIBERTY_UNIVERSE}
174   set_reachable (mark: like reachable_mark) is
175      do
176         if not is_reachable then
177            log.trace.put_string(once "Marked reachable the feature definition: ")
178            log.trace.put_line(feature_name.name)
179            torch.burn
180         end
181
182         if reachable_mark < mark then
183            reachable_mark := mark
184            if the_feature /= Void then
185               the_feature.mark_reachable_code(mark)
186            end
187         end
188      end
189
190feature {LIBERTY_REACHABLE, LIBERTY_REACHABLE_COLLECTION_MARKER}
191   mark_reachable_code (mark: INTEGER) is
192      do
193         set_reachable(mark)
194      end
195
196feature {ANY}
197   debug_display (o: OUTPUT_STREAM; show_details: BOOLEAN) is
198      do
199         o.put_string(once "   feature ")
200         debug_clients(o, clients)
201         if is_creation then
202            o.put_string(once " create ")
203            debug_clients(o, creation_clients)
204         end
205         if is_frozen then
206            o.put_string(once " frozen")
207         end
208         if is_prefix then
209            o.put_string(once " prefix ")
210         elseif is_infix then
211            o.put_string(once " infix ")
212         else
213            o.put_character(' ')
214         end
215         o.put_string(name.out)
216         if show_details then
217            if the_feature = Void then
218               o.put_line(once " is not yet attached")
219            else
220               o.put_line(once " is")
221               the_feature.debug_display(o, 2)
222               o.put_line(once "      end")
223            end
224         else
225            o.put_new_line
226         end
227      end
228
229feature {}
230   debug_clients (o: OUTPUT_STREAM; c: like clients) is
231      local
232         i: INTEGER
233      do
234         o.put_character('{')
235         from
236            i := c.lower
237         until
238            i > c.upper
239         loop
240            o.put_string(c.item(i).full_name.out)
241            if i < c.upper then
242               o.put_string(once ", ")
243            end
244            i := i + 1
245         end
246         o.put_character('}')
247      end
248
249feature {LIBERTY_BUILDER_TOOLS}
250   set_clients (a_clients: like clients) is
251      require
252         a_clients /= Void
253      do
254         clients := a_clients
255      ensure
256         clients = a_clients
257      end
258
259   set_the_feature (a_feature: like the_feature) is
260      require
261         a_feature.current_type = current_type
262      do
263         the_feature := a_feature
264      ensure
265         the_feature = a_feature
266      end
267
268   set_creation_clients (a_creation_clients: like creation_clients) is
269      require
270         a_creation_clients /= Void
271      do
272         creation_clients := a_creation_clients
273      ensure
274         is_creation
275         creation_clients = a_creation_clients
276      end
277
278   join (fd: like Current; a_parent_type: LIBERTY_ACTUAL_TYPE) is
279      require
280         fd.current_type = current_type
281         fd.has_precursor(a_parent_type)
282      local
283         old_feature: like the_feature
284      do
285         if not same_clients(fd.clients) then
286            --| *** TODO: warning: the inherited features don't have the same export clauses (the second set
287            --| is ignored)
288         end
289         old_feature := the_feature
290         if fd.the_feature /= Void then
291            if old_feature = Void then
292               the_feature := fd.the_feature
293            elseif old_feature.id /= fd.the_feature.id then
294               the_feature := old_feature.join(current_type, fd.the_feature, Current, fd)
295            end
296         end
297         if not has_precursor(a_parent_type) then
298            add_precursor(fd.precursor_feature(a_parent_type), a_parent_type)
299         else
300            check
301               precursor_feature(a_parent_type) = fd.precursor_feature(a_parent_type)
302            end
303         end
304      ensure
305         has_precursor(a_parent_type)
306      end
307
308   re_name (a_name: like feature_name) is
309      require
310         a_name /= Void
311      do
312         feature_name := a_name
313      ensure
314         feature_name = a_name
315      end
316
317feature {LIBERTY_FEATURE, LIBERTY_FEATURE_DEFINITION}
318   fatal_join_error_redefined_concrete (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
319      do
320         debug ("type.building")
321            log.trace.put_string(once "Cannot join redefined feature ")
322            log.trace.put_string(feature_name.name)
323            log.trace.put_string(once " from ")
324            log.trace.put_string(the_feature.definition_type.full_name)
325            log.trace.put_string(once " with concrete feature ")
326            log.trace.put_string(with.feature_name.name)
327            log.trace.put_string(once " from ")
328            log.trace.put_string(with.the_feature.definition_type.full_name)
329            log.trace.put_string(once " in type ")
330            log.trace.put_line(type.full_name)
331            breakpoint
332         end
333         not_yet_implemented
334      ensure
335         errors.has_error
336      end
337
338   fatal_join_error_concrete_redefined (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
339      do
340         with.fatal_join_error_redefined_concrete(type, Current)
341      ensure
342         errors.has_error
343      end
344
345   fatal_join_error_concrete_concrete (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
346      do
347         debug ("type.building")
348            log.trace.put_string(once "Cannot join concrete feature ")
349            log.trace.put_string(feature_name.name)
350            log.trace.put_string(once " from ")
351            log.trace.put_string(the_feature.definition_type.full_name)
352            log.trace.put_string(once " with concrete feature ")
353            log.trace.put_string(with.feature_name.name)
354            log.trace.put_string(once " from ")
355            log.trace.put_string(with.the_feature.definition_type.full_name)
356            log.trace.put_string(once " in type ")
357            log.trace.put_line(type.full_name)
358            breakpoint
359         end
360         not_yet_implemented
361      ensure
362         errors.has_error
363      end
364
365feature {LIBERTY_BUILDER_TOOLS, LIBERTY_FEATURE_DEFINITION}
366   add_precursor (a_precursor_feature: LIBERTY_FEATURE; a_precursor_type: LIBERTY_ACTUAL_TYPE) is
367      require
368         not has_precursor(a_precursor_type)
369         a_precursor_feature.current_type = current_type
370      do
371         if precursors = Void then
372            create {HASHED_DICTIONARY[LIBERTY_FEATURE, LIBERTY_ACTUAL_TYPE]} precursors.with_capacity(3)
373         end
374         precursors.add(a_precursor_feature, a_precursor_type)
375         torch.burn
376      ensure
377         precursor_feature(a_precursor_type) = a_precursor_feature
378      end
379
380   has_precursor (a_precursor_type: LIBERTY_ACTUAL_TYPE): BOOLEAN is
381      do
382         if precursors /= Void then
383            if a_precursor_type /= Void then
384               Result := precursors.fast_has(a_precursor_type)
385            else
386               Result := precursors.count = 1
387            end
388         end
389      end
390
391   precursor_feature (a_precursor_type: LIBERTY_ACTUAL_TYPE): LIBERTY_FEATURE is
392      require
393         has_precursor(a_precursor_type)
394      do
395         if a_precursor_type /= Void then
396            Result := precursors.fast_at(a_precursor_type)
397         else
398            Result := precursors.first
399         end
400      end
401
402feature {LIBERTY_ACTUAL_TYPE}
403   copy_precursors (other: like Current) is
404      local
405         f: LIBERTY_FEATURE; t: LIBERTY_ACTUAL_TYPE
406         i: INTEGER
407      do
408         if other.precursors /= Void then
409            if precursors = Void then
410               precursors := other.precursors
411            else
412               from
413                  i := precursors.lower
414               until
415                  i > precursors.upper
416               loop
417                  t := precursors.key(i)
418                  f := precursors.item(i)
419                  if precursors.fast_has(t) then
420                     breakpoint
421                  else
422                     precursors.add(f, t)
423                  end
424                  i := i + 1
425               end
426            end
427         end
428      end
429
430feature {}
431   same_clients (a_clients: like clients): BOOLEAN is
432      do
433         Result := clients.count = a_clients.count
434            and then include(clients, a_clients)
435            and then include(a_clients, clients)
436      end
437
438   include (set, subset: like clients): BOOLEAN is
439      local
440         i, j: INTEGER
441      do
442         from
443            Result := set.count >= subset.count
444            i := subset.lower
445         until
446            not Result or else i > subset.upper
447         loop
448            from
449               Result := False
450               j := set.lower
451            until
452               Result or else j > set.upper
453            loop
454               Result := set.item(j) = subset.item(i)
455               j := j + 1
456            end
457            i := i + 1
458         end
459      end
460
461feature {}
462   make (a_name: like feature_name; a_type: like current_type; a_clients: like clients; a_frozen: like is_frozen; a_position: like position) is
463      require
464         a_name /= Void
465         a_type /= Void
466         a_clients /= Void
467         a_position /= Void
468      do
469         feature_name := a_name
470         current_type := a_type
471         clients := a_clients
472         is_frozen := a_frozen
473         position := a_position
474
475         debug ("full_name")
476            debug_full_name := a_name.full_name.out
477         end
478      ensure
479         feature_name = a_name
480         current_type = a_type
481         clients = a_clients
482         is_frozen = a_frozen
483         position = a_position
484      end
485
486   specialized (a_name: like feature_name; a_type: like current_type; a_creation_clients: like creation_clients; a_clients: like clients;
487                a_frozen: like is_frozen; a_feature: like the_feature; a_precursors: like precursors; a_position: like position) is
488      do
489         make(a_name, a_type, a_clients, a_frozen, a_position)
490         the_feature := a_feature
491         precursors := a_precursors
492         if a_creation_clients /= Void then
493            set_creation_clients(a_creation_clients)
494         end
495
496         debug ("full_name")
497            debug_full_name := a_name.full_name.out
498         end
499      end
500
501   torch: LIBERTY_ENLIGHTENING_THE_WORLD
502   errors: LIBERTY_ERRORS
503
504   debug_full_name: STRING
505
506feature {LIBERTY_FEATURE_DEFINITION}
507   precursors: DICTIONARY[LIBERTY_FEATURE, LIBERTY_ACTUAL_TYPE]
508         -- For correct "Precursor" management. All the features have the same `current_type'.
509
510feature {ANY}
511   accept (v: VISITOR) is
512      local
513         v0: LIBERTY_FEATURE_DEFINITION_VISITOR
514      do
515         v0 ::= v
516         v0.visit_liberty_feature_definition(Current)
517      end
518
519invariant
520   feature_name /= Void
521   clients /= Void
522   the_feature /= Void implies the_feature.current_type = current_type
523
524end