PageRenderTime 41ms CodeModel.GetById 19ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/src/tools/interpreter/liberty_interpreter_feature_call.e

http://github.com/tybor/Liberty
Specman e | 734 lines | 647 code | 68 blank | 19 comment | 40 complexity | ee0148e5933a45875478826d0f337141 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_INTERPRETER_FEATURE_CALL
 16
 17inherit
 18   LIBERTY_FEATURE_VISITOR
 19
 20insert
 21   LIBERTY_TAGS
 22   LOGGING
 23
 24creation {LIBERTY_INTERPRETER}
 25   make, make_precursor
 26
 27feature {ANY}
 28   name: FIXED_STRING
 29   target: LIBERTY_INTERPRETER_OBJECT
 30   parameters: TRAVERSABLE[LIBERTY_INTERPRETER_OBJECT]
 31   position: LIBERTY_POSITION
 32
 33   definition_type: LIBERTY_ACTUAL_TYPE is
 34      do
 35         Result := bound_feature.definition_type
 36      end
 37
 38   returned_static_type: LIBERTY_ACTUAL_TYPE
 39
 40feature {LIBERTY_INTERPRETER_EXTERNAL_PLUGINS}
 41   bound_feature: LIBERTY_FEATURE
 42
 43feature {LIBERTY_INTERPRETER}
 44   call (debug_steps: LIBERTY_INTERPRETER_DEBUGGER_STEPS) is
 45      do
 46         check not prepare end
 47
 48         if log.is_trace then
 49            log_call(once "Calling")
 50         end
 51
 52         prepare := True
 53         bound_feature.accept(Current)
 54         prepare := False
 55
 56         debug_steps.enter_call
 57
 58         if options.is_invariant_checked then
 59            check_invariant
 60         end
 61         if options.is_require_checked then
 62            check_precondition
 63         end
 64         debug ("interpreter.call.steps")
 65            debug_step(once"Calling the feature")
 66         end
 67         bound_feature.accept(Current)
 68         if parameters = Void and then options.is_ensure_checked then
 69            -- Can happen only when semi-evaluated built-in externals are used
 70            -- In that case the postcondition must not depend on the arguments...
 71            prepare_postcondition
 72         end
 73         if options.is_ensure_checked then
 74            check_postcondition
 75         end
 76         if options.is_invariant_checked then
 77            check_invariant
 78         end
 79         debug_steps.exit_call
 80
 81         if log.is_trace then
 82            log_call(once "Returning from")
 83         end
 84      end
 85
 86feature {LIBERTY_FEATURE_ACCELERATOR}
 87   accelerate_call (a: LIBERTY_FEATURE_ACCELERATOR) is
 88      do
 89         bound_feature.accelerate_call(a)
 90      end
 91
 92feature {LIBERTY_INTERPRETER, LIBERTY_INTERPRETER_EXTERNAL_BUILTINS_CALLER}
 93   evaluate_parameters is
 94      local
 95         i: INTEGER; p: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT]
 96         val: LIBERTY_INTERPRETER_OBJECT
 97         formal_type: LIBERTY_ACTUAL_TYPE; actual_type: LIBERTY_KNOWN_TYPE
 98      do
 99         if parameters = Void then
100            interpreter.set_evaluating_parameters(Current)
101            if bound_feature.parameters.count /= actuals.count then
102               interpreter.fatal_error("Bad parameters count: expected " + bound_feature.parameters.count.out
103                                       + " but got " + actuals.count.out, position)
104            end
105            check
106               bound_feature.parameters.lower = actuals.lower
107            end
108            from
109               create p.with_capacity(actuals.count)
110               i := actuals.lower
111            until
112               i > actuals.upper
113            loop
114               actuals.item(i).accept(interpreter.expressions)
115               val := interpreter.expressions.eval_as_right_value
116               formal_type ::= bound_feature.parameters.item(i).result_type.known_type
117               actual_type := val.type.known_type
118               if actual_type.is_conform_to(formal_type) then
119                  p.add_last(val)
120               elseif actual_type.converts_to(formal_type) then
121                  p.add_last(interpreter.object_converter.convert_object(val, formal_type))
122               else
123                  interpreter.fatal_error("Bad object type: " + actual_type.full_name + " does not conform or convert to " + formal_type.full_name, actuals.item(i).position)
124                  p.add_last(val)
125               end
126               i := i + 1
127            end
128            parameters := p
129            interpreter.unset_evaluating_parameters(Current)
130
131            prepare_parameter_map(bound_feature)
132            debug ("interpreter.call.internals")
133               show_parameter_map(std_output)
134               std_output.put_new_line
135            end
136            if options.is_ensure_checked then
137               prepare_postcondition
138            end
139         end
140      end
141
142feature {LIBERTY_INTERPRETER, LIBERTY_INTERPRETER_EXTERNAL_BUILTIN_CALL, LIBERTY_INTERPRETER_EXTERNAL_PLUGINS}
143   returned_object: LIBERTY_INTERPRETER_OBJECT
144
145   set_returned_object (a_returned_object: like returned_object) is
146      do
147         if returned_static_type = Void then
148            check a_returned_object = Void end
149         else
150            returned_object := a_returned_object
151            debug ("interpreter.call.internals")
152               std_output.put_string(once " >>> Feature ")
153               std_output.put_string(name)
154               std_output.put_string(once " @")
155               std_output.put_string(to_pointer.out)
156               std_output.put_string(once ": setting Result to ")
157               interpreter.object_printer.print_object(std_output, returned_object, 2)
158            end
159         end
160      ensure
161         returned_object = a_returned_object
162      end
163
164   local_static_type (local_name: FIXED_STRING): LIBERTY_ACTUAL_TYPE is
165      do
166         Result := local_types.reference_at(local_name)
167      end
168
169   set_local_value (local_name: FIXED_STRING; value: LIBERTY_INTERPRETER_OBJECT) is
170      do
171         local_map.put(value, local_name)
172      end
173
174   local_value (local_name: FIXED_STRING): LIBERTY_INTERPRETER_OBJECT is
175      do
176         if local_map = Void then
177            interpreter.fatal_error("Locals map not ready!", position)
178         end
179         Result := local_map.fast_reference_at(local_name)
180      end
181
182   parameter (parameter_name: FIXED_STRING): LIBERTY_INTERPRETER_OBJECT is
183      do
184         if parameter_map = Void then
185            interpreter.fatal_error("Parameters map not ready!", position)
186         end
187         Result := parameter_map.fast_reference_at(parameter_name)
188      end
189
190   writable_feature_static_type (a_feature_name: LIBERTY_FEATURE_NAME): LIBERTY_ACTUAL_TYPE is
191      do
192         Result ::= target.type.feature_definition(a_feature_name).result_type.known_type
193      end
194
195   set_writable_feature (a_name: LIBERTY_FEATURE_NAME; a_value: LIBERTY_INTERPRETER_OBJECT) is
196      local
197         struct: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
198      do
199         struct ::= target
200         struct.put_attribute(a_name.name, a_value)
201      end
202
203   writable_feature (a_name: LIBERTY_FEATURE_NAME): LIBERTY_INTERPRETER_OBJECT is
204      local
205         struct: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
206      do
207         struct ::= target
208         Result := struct.attribute_object(a_name.name)
209      end
210
211   raised_exception: LIBERTY_INTERPRETER_EXCEPTION
212
213   raise (a_exception: like raised_exception) is
214      do
215         raised_exception := a_exception
216      ensure
217         raised_exception = a_exception
218      end
219
220feature {ANY}
221   show_stack (o: OUTPUT_STREAM) is
222      do
223         o.put_string(once "Feature {")
224         o.put_string(target.type.full_name)
225         o.put_string(once "}.")
226         o.put_string(name)
227         o.put_string(once " @")
228         o.put_line(to_pointer.out)
229         if not position.is_unknown then
230            o.put_character('%T')
231            position.show(o)
232         end
233         o.put_new_line
234         o.put_string(once "Current = ")
235         interpreter.object_printer.print_object(o, target, 0)
236         if returned_static_type /= Void then
237            o.put_new_line
238            o.put_string(once "Result = ")
239            interpreter.object_printer.print_object(o, returned_object, 0)
240         end
241
242         show_parameter_map(o)
243         show_local_map(o)
244      end
245
246feature {}
247   show_parameter_map (o: OUTPUT_STREAM) is
248      do
249         show_map(parameter_map, once "Parameters", o)
250      end
251
252   show_local_map (o: OUTPUT_STREAM) is
253      do
254         show_map(local_map, once "Locals", o)
255      end
256
257   show_map (map: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]; tag: STRING; o: OUTPUT_STREAM) is
258      local
259         i: INTEGER; obj: LIBERTY_INTERPRETER_OBJECT
260      do
261         if map = Void then
262            o.put_new_line
263            o.put_string(tag)
264            o.put_line(once " map not yet computed")
265         elseif not map.is_empty then
266            o.put_new_line
267            o.put_string(tag)
268            o.put_line(once ":")
269            from
270               i := map.lower
271            until
272               i > map.upper
273            loop
274               o.put_string(once "   ")
275               o.put_string(map.key(i))
276               o.put_string(once " = ")
277               obj := map.item(i)
278               interpreter.object_printer.print_object(o, obj, 1)
279               i := i + 1
280            end
281         end
282      end
283
284feature {LIBERTY_FEATURE_ATTRIBUTE}
285   visit_liberty_feature_attribute (v: LIBERTY_FEATURE_ATTRIBUTE) is
286      local
287         t: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
288         fn: LIBERTY_FEATURE_NAME
289         actual_type: LIBERTY_ACTUAL_TYPE
290      do
291         if prepare then
292            evaluate_parameters
293         else
294            if t ?:= target then
295               t ::= target
296               if t.has_attribute(name) then
297                  set_returned_object(t.attribute_object(name))
298               else
299                  create fn.make(name)
300                  if t.type.has_feature(fn) then
301                     -- at creation time
302                     actual_type ::= t.type.feature_definition(fn).result_type.known_type
303                     set_returned_object(interpreter.default_object(actual_type, t.position))
304                     t.put_attribute(name, returned_object)
305                  else
306                     interpreter.fatal_error("No such attribute: " + name, position)
307                  end
308               end
309            else
310               --|*** TODO: not good. Native objects may have attributes too (e.g. string)
311               interpreter.fatal_error("No such attribute: " + name, position)
312            end
313         end
314      end
315
316feature {LIBERTY_FEATURE_CONSTANT}
317   visit_liberty_feature_constant (v: LIBERTY_FEATURE_CONSTANT) is
318      do
319         if prepare then
320            evaluate_parameters
321         else
322            v.expression.accept(interpreter.expressions)
323            set_returned_object(interpreter.expressions.eval_as_right_value)
324         end
325      end
326
327feature {LIBERTY_FEATURE_DEFERRED}
328   visit_liberty_feature_deferred (v: LIBERTY_FEATURE_DEFERRED) is
329      do
330         evaluate_parameters
331         interpreter.fatal_error("Deferred feature called", position)
332      end
333
334feature {LIBERTY_FEATURE_DO}
335   visit_liberty_feature_do (v: LIBERTY_FEATURE_DO) is
336      do
337         if prepare then
338            evaluate_parameters
339            prepare_local_map(v)
340         else
341            v.block_instruction.accept(interpreter.instructions)
342         end
343      end
344
345feature {LIBERTY_FEATURE_EXTERNAL}
346   visit_liberty_feature_external (v: LIBERTY_FEATURE_EXTERNAL) is
347      do
348         if prepare then
349            inspect
350               v.external_def
351            when "built_in" then
352               -- nothing
353            when "plug_in" then
354               evaluate_parameters
355            else
356               not_yet_implemented
357            end
358         else
359            inspect
360               v.external_def
361            when "built_in" then
362               interpreter.builtins.call(Current)
363            when "plug_in" then
364               interpreter.plugins.call(Current, v.alias_def, position)
365            else
366               not_yet_implemented
367            end
368         end
369      end
370
371feature {LIBERTY_FEATURE_ONCE}
372   visit_liberty_feature_once (v: LIBERTY_FEATURE_ONCE) is
373      local
374         tags: LIBERTY_TAGS
375      do
376         if prepare then
377            evaluate_parameters
378            if not tags.once_flag.is_set(v.original) then
379               prepare_local_map(v)
380            end
381         elseif tags.once_flag.is_set(v.original) then
382            log.trace.put_line(once "Once feature already called")
383            set_returned_object(tags.once_flag.value(v.original))
384         else
385            log.trace.put_line(once "Evaluating once feature")
386            v.block_instruction.accept(interpreter.instructions)
387            tags.once_flag.add(returned_object, v.original)
388         end
389      end
390
391feature {LIBERTY_FEATURE_REDEFINED}
392   visit_liberty_feature_redefined (v: LIBERTY_FEATURE_REDEFINED) is
393      do
394         v.redefined_feature.accept(Current)
395      end
396
397feature {LIBERTY_FEATURE_UNIQUE}
398   visit_liberty_feature_unique (v: LIBERTY_FEATURE_UNIQUE) is
399      do
400         if prepare then
401            evaluate_parameters
402         else
403            not_yet_implemented
404         end
405      end
406
407feature {}
408   make (a_interpreter: like interpreter; a_target: like target; a_feature_definition: LIBERTY_FEATURE_DEFINITION; a_actuals: like actuals; a_position: like position) is
409      require
410         a_interpreter /= Void
411         a_target /= Void
412         a_feature_definition /= Void
413         a_actuals /= Void
414         a_position /= Void
415      do
416         feature_name := a_feature_definition.feature_name
417         name := feature_name.full_name
418         interpreter := a_interpreter
419         target := a_target
420         actuals := a_actuals
421         position := a_position
422         bound_feature := a_feature_definition.the_feature.bound(a_target.type)
423         if bound_feature.result_type /= Void then
424            returned_static_type ::= bound_feature.result_type.known_type
425         end
426
427         create {ARRAY_DICTIONARY[TUPLE[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING, LIBERTY_POSITION], LIBERTY_EXPRESSION]} old_values.with_capacity(0)
428
429         if returned_static_type /= Void then
430            returned_object := interpreter.default_object(returned_static_type, position)
431         end
432      ensure
433         interpreter = a_interpreter
434         target = a_target
435         actuals = a_actuals
436      end
437
438   make_precursor (a_interpreter: like interpreter; a_target: like target; a_precursor: LIBERTY_FEATURE; a_actuals: like actuals; a_position: like position) is
439      require
440         a_interpreter /= Void
441         a_target /= Void
442         a_actuals /= Void
443         a_position /= Void
444      do
445         name := name_precursor
446         interpreter := a_interpreter
447         target := a_target
448         actuals := a_actuals
449         position := a_position
450         bound_feature := a_precursor
451         if bound_feature.result_type /= Void then
452            returned_static_type ::= bound_feature.result_type.known_type
453         end
454
455         create {ARRAY_DICTIONARY[TUPLE[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING, LIBERTY_POSITION], LIBERTY_EXPRESSION]} old_values.with_capacity(0)
456      ensure
457         interpreter = a_interpreter
458         target = a_target
459         actuals = a_actuals
460      end
461
462   feature_name: LIBERTY_FEATURE_NAME
463
464   name_precursor: FIXED_STRING is
465      once
466         Result := "Precursor".intern
467      end
468
469   interpreter: LIBERTY_INTERPRETER
470   actuals: TRAVERSABLE[LIBERTY_EXPRESSION]
471
472   parameter_types: DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING]
473   parameter_map: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]
474
475   local_types: DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING]
476   local_map: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]
477
478   empty_types: DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING] is
479      once
480         create {AVL_DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING]} Result.make
481      end
482
483   empty_map: DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING] is
484      once
485         create {AVL_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} Result.make
486      end
487
488   prepare_parameter_map (f: LIBERTY_FEATURE) is
489      require
490         parameters /= Void
491      local
492         i: INTEGER; p: LIBERTY_PARAMETER
493         actual_type: LIBERTY_ACTUAL_TYPE
494      do
495         if f.parameters.count /= actuals.count then
496            interpreter.fatal_error("Bad number of arguments: expected " + f.parameters.count.out
497                                    + " but got " + actuals.count.out, position)
498         end
499         if actuals.is_empty then
500            parameter_types := empty_types
501            parameter_map := empty_map
502         else
503            check
504               f.parameters.lower = actuals.lower
505               parameters.lower = actuals.lower
506            end
507            create {HASHED_DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING]} parameter_types.with_capacity(actuals.count)
508            create {HASHED_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} parameter_map.with_capacity(actuals.count)
509            from
510               i := actuals.lower
511            until
512               i > actuals.upper
513            loop
514               p := f.parameters.item(i)
515               actual_type ::= p.result_type.known_type
516               parameter_types.add(actual_type, p.name)
517               parameter_map.add(parameters.item(i), p.name)
518               i := i + 1
519            end
520         end
521      ensure
522         parameter_types /= Void
523         parameter_map /= Void
524      end
525
526   prepare_local_map (f: LIBERTY_FEATURE_ROUTINE) is
527      local
528         i: INTEGER; l: LIBERTY_LOCAL; def: LIBERTY_INTERPRETER_OBJECT
529         actual_type: LIBERTY_ACTUAL_TYPE
530      do
531         if f.locals.is_empty then
532            local_types := empty_types
533            local_map := empty_map
534         else
535            create {HASHED_DICTIONARY[LIBERTY_ACTUAL_TYPE, FIXED_STRING]} local_types.with_capacity(f.locals.count)
536            create {HASHED_DICTIONARY[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING]} local_map.with_capacity(f.locals.count)
537            from
538               i := f.locals.lower
539            until
540               i > f.locals.upper
541            loop
542               l := f.locals.item(i)
543               actual_type ::= l.result_type.known_type
544               local_types.add(actual_type, l.name)
545               def := interpreter.default_object(actual_type, l.position)
546               local_map.add(def, l.name)
547               i := i + 1
548            end
549         end
550      ensure
551         local_types /= Void
552         local_map /= Void
553      end
554
555feature {LIBERTY_INTERPRETER}
556   has_old_value (a_expression: LIBERTY_EXPRESSION): BOOLEAN is
557      do
558         Result := old_values.fast_has(a_expression)
559      end
560
561   old_value (a_expression: LIBERTY_EXPRESSION): LIBERTY_INTERPRETER_OBJECT is
562      require
563         has_old_value(a_expression)
564      local
565         t: TUPLE[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING, LIBERTY_POSITION]
566      do
567         t := old_values.fast_at(a_expression)
568         if t.second /= Void then
569            interpreter.fatal_error(t.second, t.third)
570         end
571         Result := t.first
572      end
573
574   add_old_value (a_expression: LIBERTY_EXPRESSION; a_value: LIBERTY_INTERPRETER_OBJECT; a_fatal_error: FIXED_STRING; a_fatal_position: LIBERTY_POSITION) is
575      require
576         not has_old_value(a_expression)
577      do
578         old_values.add([a_value, a_fatal_error, a_fatal_position], a_expression)
579         debug ("interpreter.call.internals")
580            std_output.put_string(once " >>> Feature ")
581            std_output.put_string(name)
582            std_output.put_string(once " @")
583            std_output.put_string(to_pointer.out)
584            std_output.put_string(once ": adding old value: ")
585            interpreter.object_printer.print_object(std_output, a_value, 2)
586         end
587      ensure
588         old_values.fast_at(a_expression).first = a_value
589         old_values.fast_at(a_expression).second = a_fatal_error
590         old_values.fast_at(a_expression).third = a_fatal_position
591         a_fatal_error = Void implies old_value(a_expression) = a_value
592      end
593
594feature {}
595   check_invariant is
596      require
597         options.is_invariant_checked
598      do
599         debug ("interpreter.call.steps")
600            debug_step(once "Checking invariant")
601         end
602         interpreter.assertions.validate(target.type.the_invariant, once "Invariant")
603         debug ("interpreter.call.steps")
604            debug_step(once "Done checking invariant")
605         end
606      end
607
608   check_precondition is
609      require
610         options.is_require_checked
611      do
612         debug ("interpreter.call.steps")
613            debug_step(once "Checking precondition")
614         end
615         interpreter.assertions.validate(bound_feature.precondition, once "Precondition")
616         debug ("interpreter.call.steps")
617            debug_step(once "Done checking precondition")
618         end
619      end
620
621   prepare_postcondition is
622      require
623         options.is_ensure_checked
624      do
625         debug ("interpreter.call.steps")
626            debug_step(once "Preparing postcondition (gathering old values)")
627         end
628         interpreter.postcondition_browser.gather_old(bound_feature.postcondition)
629         debug ("interpreter.call.steps")
630            debug_step(once "Done preparing postcondition (gathering old values)")
631         end
632      end
633
634   check_postcondition is
635      require
636         options.is_ensure_checked
637      do
638         debug ("interpreter.call.steps")
639            debug_step(once "Checking postcondition")
640         end
641         interpreter.assertions.validate(bound_feature.postcondition, once "Postcondition")
642         debug ("interpreter.call.steps")
643            debug_step(once "Done checking postcondition")
644         end
645      end
646
647   options: LIBERTY_INTERPRETER_OPTIONS
648
649   old_values: DICTIONARY[TUPLE[LIBERTY_INTERPRETER_OBJECT, FIXED_STRING, LIBERTY_POSITION], LIBERTY_EXPRESSION]
650   prepare: BOOLEAN
651
652   debug_step (step: STRING) is
653      do
654         std_output.put_new_line
655         std_output.put_string(once " >>> ")
656         std_output.put_string(name)
657         std_output.put_string(once " @")
658         std_output.put_string(to_pointer.out)
659         std_output.put_string(once ": ")
660         std_output.put_line(step)
661      end
662
663   log_call (tag: STRING) is
664      require
665         log.is_trace
666      local
667         i: INTEGER; log_out: OUTPUT_STREAM
668         formals: TRAVERSABLE[LIBERTY_PARAMETER]
669         p: LIBERTY_PARAMETER
670      do
671         log_out := log.trace
672         log_out.put_string(tag)
673         log_out.put_string(once " feature {")
674         log_out.put_string(bound_feature.current_type.full_name)
675         log_out.put_string(once "}.")
676         log_out.put_string(name)
677         formals := bound_feature.parameters
678         if not formals.is_empty then
679            log_out.put_character(' ')
680            log_out.put_character('(')
681            from
682               i := formals.lower
683            until
684               i > formals.upper
685            loop
686               if i > formals.lower then
687                  log_out.put_string(once ", ")
688               end
689               log_out.put_string(formals.item(i).result_type.full_name)
690               i := i + 1
691            end
692            log_out.put_character(')')
693         end
694         if returned_static_type /= Void then
695            log_out.put_string(once ": ")
696            log_out.put_string(returned_static_type.full_name)
697         end
698         if position.is_unknown then
699            log_out.put_new_line
700         else
701            log_out.put_character(' ')
702            position.show(log_out)
703         end
704         log_out.put_string(once " - Current=")
705         interpreter.object_printer.print_object(log_out, target, 1)
706         if parameter_map /= Void then
707            from
708               i := formals.lower
709            until
710               i > formals.upper
711            loop
712               p := formals.item(i)
713               log_out.put_string(once " - ")
714               log_out.put_string(p.name)
715               log_out.put_character('=')
716               interpreter.object_printer.print_object(log_out, parameter_map.fast_at(p.name), 1)
717               i := i + 1
718            end
719         end
720         if returned_object /= Void then
721            log_out.put_string(once " - Result=")
722            interpreter.object_printer.print_object(log_out, returned_object, 1)
723         end
724      end
725
726invariant
727   interpreter /= Void
728   actuals /= Void
729   target /= Void
730   name /= Void
731
732   not interpreter.gathering_old_values implies ((returned_static_type = Void) = (returned_object = Void))
733
734end -- class LIBERTY_INTERPRETER_FEATURE_CALL