PageRenderTime 30ms CodeModel.GetById 13ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 1ms

/src/tools/semantics/code/feature_local_context/liberty_feature_definition_context.e

http://github.com/tybor/Liberty
Specman e | 520 lines | 445 code | 59 blank | 16 comment | 22 complexity | fc28715b26240a315fb41a452ad4bd36 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_CONTEXT
 16
 17inherit
 18   LIBERTY_FEATURE_LOCAL_CONTEXT
 19
 20insert
 21   LIBERTY_AST_HANDLER
 22
 23create {LIBERTY_BUILDER_TOOLS}
 24   make
 25
 26feature {ANY}
 27   current_type: LIBERTY_ACTUAL_TYPE is
 28      do
 29         Result := current_entity.result_type
 30      end
 31
 32   result_type: LIBERTY_TYPE is
 33      do
 34         if result_entity /= Void then
 35            Result := result_entity.result_type
 36         end
 37      end
 38
 39   parameters: TRAVERSABLE[LIBERTY_PARAMETER] is
 40      do
 41         Result := parameters_list
 42      ensure then
 43         definition: Result = parameters_list
 44      end
 45
 46   locals: TRAVERSABLE[LIBERTY_LOCAL] is
 47      do
 48         Result := locals_list
 49      ensure then
 50         definition: Result = locals_list
 51      end
 52
 53   is_parameter (name: ABSTRACT_STRING): BOOLEAN is
 54      do
 55         Result := parameters_map.has(name.intern)
 56      end
 57
 58   parameter (name: ABSTRACT_STRING): LIBERTY_PARAMETER is
 59      do
 60         Result := parameters_map.reference_at(name.intern)
 61      end
 62
 63   is_local (name: ABSTRACT_STRING): BOOLEAN is
 64      do
 65         Result := locals_map.has(name.intern)
 66      end
 67
 68   local_var (name: ABSTRACT_STRING): LIBERTY_LOCAL is
 69      do
 70         Result := locals_map.reference_at(name.intern)
 71      end
 72
 73   current_entity: LIBERTY_CURRENT
 74   result_entity: LIBERTY_RESULT
 75
 76   can_retry: BOOLEAN is True
 77
 78   retry_instruction (a_position: LIBERTY_POSITION): LIBERTY_RETRY is
 79      do
 80         create Result.make(a_position)
 81         retries.add_last(Result)
 82      end
 83
 84feature {LIBERTY_BUILDER_TOOLS, LIBERTY_FEATURE_LOCAL_CONTEXT}
 85   add_parameter (a_parameter: LIBERTY_PARAMETER) is
 86      do
 87         parameters_list.add_last(a_parameter)
 88         parameters_map.add(a_parameter, a_parameter.name)
 89      end
 90
 91   add_local (a_local: LIBERTY_LOCAL) is
 92      do
 93         locals_list.add_last(a_local)
 94         locals_map.add(a_local, a_local.name)
 95      end
 96
 97   reconcile_retry_instructions (a_feature: LIBERTY_FEATURE) is
 98      do
 99         retries.do_all(agent {LIBERTY_RETRY}.set_feature(a_feature))
100      end
101
102   set_result_type (a_result_type: like result_type) is
103      do
104         result_entity := a_result_type.result_entity
105      end
106
107   set_feature_names (a_feature_names: like feature_names) is
108      require
109         a_feature_names /= Void
110      do
111         feature_names := a_feature_names
112         compute_written_feature_names
113         compute_best_accelerator
114      ensure
115         feature_names = a_feature_names
116         written_feature_names /= Void
117         best_accelerator /= Void
118      end
119
120   best_accelerator: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]]
121
122   written_feature_names: FIXED_STRING
123
124   find_precursor (parent: LIBERTY_ACTUAL_TYPE; redefined_features: DICTIONARY[LIBERTY_FEATURE_REDEFINED, LIBERTY_FEATURE_NAME];
125                   ast: LIBERTY_AST_ONE_CLASS; file: FIXED_STRING): LIBERTY_FEATURE is
126      local
127         i: INTEGER; fn: LIBERTY_AST_FEATURE_NAME
128      do
129         from
130            i := feature_names.lower
131         until
132            Result /= Void or else i > feature_names.upper
133         loop
134            fn ::= feature_names.item(i)
135            Result := redefined_features.reference_at(create {LIBERTY_FEATURE_NAME}.make_from_ast(fn.feature_name_or_alias, ast, file))
136            i := i + 1
137         end
138         if Result /= Void then
139            Result := Result.find_precursor(parent)
140         end
141         if Result = Void then
142            breakpoint
143         end
144      end
145
146feature {LIBERTY_FEATURE, LIBERTY_SEMANTICS_BUILDER}
147   specialized_in (a_type: like current_type): like Current is
148      do
149         Result := twin
150         Result.set_specialized_in(a_type)
151      end
152
153   debug_display_signature (o: OUTPUT_STREAM) is
154      local
155         i: INTEGER
156      do
157         if not parameters_list.is_empty then
158            o.put_character('(')
159            from
160               i := parameters_list.lower
161            until
162               i > parameters_list.upper
163            loop
164               if i > parameters_list.lower then
165                  o.put_string(once "; ")
166               end
167               o.put_string(parameters_list.item(i).name)
168               o.put_string(once ": ")
169               o.put_string(parameters_list.item(i).result_type.full_name)
170               i := i + 1
171            end
172            o.put_character(')')
173         end
174         if result_type /= Void then
175            o.put_string(once ": ")
176            o.put_string(result_type.full_name)
177         end
178      end
179
180feature {LIBERTY_FEATURE_DEFINITION_CONTEXT}
181   set_specialized_in (a_type: like current_type) is
182      local
183         i: INTEGER; p: LIBERTY_PARAMETER; l: LIBERTY_LOCAL
184         pl: like parameters_list; pm: like parameters_map
185         ll: like locals_list; lm: like locals_map
186      do
187         current_entity := a_type.current_entity
188
189         if result_entity /= Void then
190            set_result_type(result_type.specialized_in(a_type))
191         end
192
193         from
194            pl := parameters_list
195            pm := parameters_map
196            i := pl.lower
197         until
198            i > pl.upper
199         loop
200            p := pl.item(i).specialized_in(a_type)
201            if p /= pl.item(i) then
202               if pl = parameters_list then
203                  pl := pl.twin
204                  pm := pm.twin
205               end
206               pl.put(p, i)
207               pm.put(p, p.name)
208            end
209            i := i + 1
210         end
211         if pl /= parameters_list then
212            parameters_list := pl
213            parameters_map := pm
214         end
215
216         from
217            ll := locals_list
218            lm := locals_map
219            i := ll.lower
220         until
221            i > ll.upper
222         loop
223            l := ll.item(i).specialized_in(a_type)
224            if l /= ll.item(i) then
225               if ll = locals_list then
226                  ll := ll.twin
227                  lm := lm.twin
228               end
229               ll.put(l, i)
230               lm.put(l, l.name)
231            end
232            i := i + 1
233         end
234         if ll /= locals_list then
235            locals_list := ll
236            locals_map := lm
237         end
238
239         --|*** TODO: retries
240      end
241
242feature {}
243   parameters_map: DICTIONARY[LIBERTY_PARAMETER, FIXED_STRING]
244   parameters_list: COLLECTION[LIBERTY_PARAMETER]
245   locals_map: DICTIONARY[LIBERTY_LOCAL, FIXED_STRING]
246   locals_list: COLLECTION[LIBERTY_LOCAL]
247   retries: COLLECTION[LIBERTY_RETRY]
248   feature_names: EIFFEL_LIST_NODE
249
250   make (a_current_type: like current_type) is
251      require
252         a_current_type /= Void
253      do
254         current_entity := a_current_type.current_entity
255         create {FAST_ARRAY[LIBERTY_PARAMETER]} parameters_list.make(0)
256         create {HASHED_DICTIONARY[LIBERTY_PARAMETER, FIXED_STRING]} parameters_map.with_capacity(3)
257         create {FAST_ARRAY[LIBERTY_LOCAL]} locals_list.make(0)
258         create {HASHED_DICTIONARY[LIBERTY_LOCAL, FIXED_STRING]} locals_map.with_capacity(3)
259         create {FAST_ARRAY[LIBERTY_RETRY]} retries.with_capacity(1)
260      ensure
261         current_type = a_current_type
262      end
263
264   compute_written_feature_names is
265      require
266         written_feature_names = Void
267      local
268         i: INTEGER
269         fn: LIBERTY_AST_FEATURE_NAME
270         fnoa: LIBERTY_AST_FEATURE_NAME_OR_ALIAS
271         buffer: STRING
272      do
273         buffer := once ""
274         buffer.clear_count
275         from
276            i := feature_names.lower
277         until
278            i > feature_names.upper
279         loop
280            fn ::= feature_names.item(i)
281            fnoa := fn.feature_name_or_alias
282            if fnoa.is_regular then
283               buffer.append(fnoa.entity_name.image.image.intern)
284            elseif fnoa.is_prefix then
285               buffer.append(once "prefix ")
286               buffer.append(fnoa.free_operator_name.image.image.intern)
287            else
288               check fnoa.is_infix end
289               buffer.append(once "infix ")
290               buffer.append(fnoa.free_operator_name.image.image.intern)
291            end
292            if i < feature_names.upper then
293               buffer.append(once ", ")
294            end
295            i := i + 1
296         end
297         written_feature_names := buffer.intern
298      ensure
299         written_feature_names /= Void
300      end
301
302   compute_best_accelerator is
303      local
304         i: INTEGER
305         fn: LIBERTY_AST_FEATURE_NAME
306         fnoa: LIBERTY_AST_FEATURE_NAME_OR_ALIAS
307         full_feature_name: STRING
308         second_best_accelerator: like best_accelerator
309      do
310         -- Heuristics to accelerate the feature calls (at least in the interpreter builtins).
311         best_accelerator := Void
312         from
313            full_feature_name := once ""
314            i := feature_names.lower
315         until
316            best_accelerator /= Void or else i > feature_names.upper
317         loop
318            fn ::= feature_names.item(i)
319            fnoa := fn.feature_name_or_alias
320            if fnoa.is_regular then
321               full_feature_name.copy(fnoa.entity_name.image.image)
322            elseif fnoa.is_prefix then
323               full_feature_name.copy(once "prefix ")
324               full_feature_name.append(fnoa.free_operator_name.image.image)
325            else
326               check fnoa.is_infix end
327               full_feature_name.copy(once "infix ")
328               full_feature_name.append(fnoa.free_operator_name.image.image)
329            end
330            inspect
331               full_feature_name
332            when "infix %"implies%"" then
333               best_accelerator := accelerator_implies
334            when "infix %"or else%"" then
335               best_accelerator := accelerator_or_else
336            when "infix %"or%"" then
337               best_accelerator := accelerator_or
338            when "infix %"xor%"" then
339               best_accelerator := accelerator_xor
340            when "infix %"and then%"" then
341               best_accelerator := accelerator_and_then
342            when "infix %"and%"" then
343               best_accelerator := accelerator_and
344            when "infix %"<=%"" then
345               best_accelerator := accelerator_less_or_equal
346            when "infix %"<%"" then
347               best_accelerator := accelerator_less_than
348            when "infix %">=%"" then
349               best_accelerator := accelerator_greater_or_equal
350            when "infix %">%"" then
351               best_accelerator := accelerator_greater_than
352            when "infix %"+%"" then
353               best_accelerator := accelerator_add
354            when "infix %"-%"" then
355               best_accelerator := accelerator_subtract
356            when "infix %"*%"" then
357               best_accelerator := accelerator_times
358            when "infix %"/%"" then
359               best_accelerator := accelerator_divide
360            when "infix %"//%"" then
361               best_accelerator := accelerator_int_divide
362            when "infix %"\\%"" then
363               best_accelerator := accelerator_int_remainder
364            when "infix %"^%"" then
365               best_accelerator := accelerator_power
366            when "prefix %"+%"" then
367               best_accelerator := accelerator_positive
368            when "prefix %"-%"" then
369               best_accelerator := accelerator_negative
370            when "prefix %"not%"" then
371               best_accelerator := accelerator_not
372            else
373               if second_best_accelerator /= Void then
374                  if fnoa.is_prefix then
375                     second_best_accelerator := accelerator_free_prefix
376                  elseif fnoa.is_infix then
377                     second_best_accelerator := accelerator_free_infix
378                  end
379               end
380            end
381            i := i + 1
382         end
383         if best_accelerator = Void then
384            if second_best_accelerator /= Void then
385               best_accelerator := second_best_accelerator
386            else
387               best_accelerator := accelerator_other
388            end
389         end
390      ensure
391         best_accelerator /= Void
392      end
393
394   errors: LIBERTY_ERRORS
395
396feature {} -- Accelerators
397   accelerator_implies: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
398      once
399         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_implies
400      end
401
402   accelerator_or_else: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
403      once
404         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_or_else
405      end
406
407   accelerator_or: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
408      once
409         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_or
410      end
411
412   accelerator_xor: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
413      once
414         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_xor
415      end
416
417   accelerator_and_then: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
418      once
419         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_and_then
420      end
421
422   accelerator_and: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
423      once
424         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_and
425      end
426
427   accelerator_less_or_equal: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
428      once
429         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_less_or_equal
430      end
431
432   accelerator_less_than: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
433      once
434         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_less_than
435      end
436
437   accelerator_greater_or_equal: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
438      once
439         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_greater_or_equal
440      end
441
442   accelerator_greater_than: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
443      once
444         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_greater_than
445      end
446
447   accelerator_add: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
448      once
449         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_add
450      end
451
452   accelerator_subtract: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
453      once
454         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_subtract
455      end
456
457   accelerator_times: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
458      once
459         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_times
460      end
461
462   accelerator_divide: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
463      once
464         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_divide
465      end
466
467   accelerator_int_divide: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
468      once
469         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_int_divide
470      end
471
472   accelerator_int_remainder: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
473      once
474         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_int_remainder
475      end
476
477   accelerator_power: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
478      once
479         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_power
480      end
481
482   accelerator_positive: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
483      once
484         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_positive
485      end
486
487   accelerator_negative: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
488      once
489         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_negative
490      end
491
492   accelerator_not: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
493      once
494         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_not
495      end
496
497   accelerator_free_prefix: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
498      once
499         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_free_prefix
500      end
501
502   accelerator_free_infix: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
503      once
504         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_free_infix
505      end
506
507   accelerator_other: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
508      once
509         Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_other
510      end
511
512invariant
513   current_type /= Void
514   parameters_list /= Void
515   locals_list /= Void
516   parameters_map /= Void
517   locals_map /= Void
518   retries /= Void
519
520end