PageRenderTime 18ms CodeModel.GetById 9ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/interpreter/liberty_interpreter.e

http://github.com/tybor/Liberty
Specman e | 845 lines | 728 code | 103 blank | 14 comment | 15 complexity | 47480b2a228bcee89ba9357233bbe157 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
 16
 17insert
 18   LOGGING
 19
 20creation {LIBERTYI}
 21   make
 22
 23feature {LIBERTYI}
 24   run is
 25      local
 26         root_object: LIBERTY_INTERPRETER_OBJECT
 27      do
 28         log.info.put_string(once "Now running {")
 29         log.info.put_string(root_type.full_name)
 30         log.info.put_string(once "}.")
 31         log.info.put_line(root_feature_name.full_name)
 32
 33         root_object := new_object(root_type, errors.unknown_position)
 34         call_feature(root_object, root_feature, root_feature_actuals, errors.unknown_position)
 35
 36         log.info.put_line(once "Finished.")
 37      end
 38
 39feature {ANY}
 40   root_type: LIBERTY_ACTUAL_TYPE
 41   root_feature_name: LIBERTY_FEATURE_NAME
 42   root_feature: LIBERTY_FEATURE_DEFINITION
 43
 44   frame_lower: INTEGER is
 45      do
 46         Result := call_stack.lower
 47      end
 48
 49   frame_upper: INTEGER is
 50      do
 51         Result := call_stack.upper
 52      end
 53
 54   current_frame: INTEGER
 55
 56   break is
 57      local
 58         done: BOOLEAN
 59      do
 60         from
 61         until
 62            done
 63         loop
 64            readline.set_prompt(once "debug> ")
 65            readline.read_line
 66            done := debugger.break(readline.last_string)
 67            if readline.end_of_input then
 68               die_with_code(0)
 69            end
 70         end
 71      end
 72
 73   show_current_frame (o: OUTPUT_STREAM) is
 74      do
 75         o.put_integer(current_frame + 1)
 76         o.put_character('%T')
 77         call_stack.item(current_frame).show_stack(o)
 78      end
 79
 80   show_stack (o: OUTPUT_STREAM) is
 81      local
 82         i: INTEGER
 83      do
 84         check
 85            call_stack.lower = 0
 86         end
 87         o.put_line(once "===================== [Bottom of stack] =====================")
 88         from
 89            i := call_stack.lower
 90         until
 91            i > call_stack.upper
 92         loop
 93            if i > call_stack.lower then
 94               o.put_line(once "-------------------------------------------------------------")
 95            end
 96            if i = current_frame then
 97               o.put_line(once "Current frame")
 98            end
 99            o.put_integer(i + 1)
100            o.put_character('%T')
101            call_stack.item(i).show_stack(o)
102            i := i + 1
103         end
104         o.put_line(once "====================== [Top of stack] =======================")
105      end
106
107   fatal_error (reason: ABSTRACT_STRING; position: LIBERTY_POSITION) is
108      do
109         if not gathering_old_values then
110            std_error.put_new_line
111            std_error.put_line(once "*** Fatal error!")
112            std_error.put_new_line
113
114            show_stack(std_error)
115
116            std_error.put_new_line
117            std_error.put_string(once "*** ")
118            std_error.put_line(reason)
119
120            if not position.is_unknown then
121               std_error.put_string(once "    ")
122               position.show(std_error)
123            end
124
125            break
126            die_with_code(1)
127         elseif not evaluating_old_value_stack.is_empty then
128            if old_fatal_error = Void then
129               old_fatal_error := reason.intern
130               old_fatal_position := position
131            end
132         end
133      end
134
135   gathering_old_values: BOOLEAN is
136      do
137         Result := gathering_old_values_counter > 0
138      end
139
140   ensure_built (a_type: LIBERTY_ACTUAL_TYPE) is
141      do
142         universe.build_types(root_type, root_feature_name, a_type)
143      end
144
145   instructions: LIBERTY_INTERPRETER_INSTRUCTIONS
146   expressions_memory: LIBERTY_INTERPRETER_EXPRESSIONS
147   assertions: LIBERTY_INTERPRETER_ASSERTION_CHECKER
148   creator: LIBERTY_INTERPRETER_OBJECT_CREATOR
149   array_creator: LIBERTY_INTERPRETER_NATIVE_ARRAY_CREATOR
150   builtins: LIBERTY_INTERPRETER_EXTERNAL_BUILTINS
151   plugins: LIBERTY_INTERPRETER_EXTERNAL_PLUGINS
152   object_printer: LIBERTY_INTERPRETER_OBJECT_PRINTER
153   object_converter: LIBERTY_INTERPRETER_OBJECT_CONVERTER
154   postcondition_browser: LIBERTY_INTERPRETER_POSTCONDITION_BROWSER
155   debugger: LIBERTY_INTERPRETER_DEBUGGER
156
157   universe: LIBERTY_UNIVERSE
158
159   expressions: LIBERTY_INTERPRETER_EXPRESSIONS is
160      do
161         if gathering_old_values then
162            Result := postcondition_browser
163         else
164            Result := expressions_memory
165         end
166      ensure
167         Result /= Void
168      end
169
170   call_feature (a_target: LIBERTY_INTERPRETER_OBJECT; feature_to_call: LIBERTY_FEATURE_DEFINITION; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION) is
171      local
172         call: LIBERTY_INTERPRETER_FEATURE_CALL
173      do
174         call := do_call(a_target, feature_to_call, actuals, a_position)
175         check
176            call.returned_object = Void
177         end
178      end
179
180   item_feature (a_target: LIBERTY_INTERPRETER_OBJECT; feature_to_call: LIBERTY_FEATURE_DEFINITION; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
181      local
182         call: LIBERTY_INTERPRETER_FEATURE_CALL
183      do
184         call := do_call(a_target, feature_to_call, actuals, a_position)
185         Result := call.returned_object
186      end
187
188   call_precursor (a_precursor: LIBERTY_FEATURE; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION) is
189      local
190         dummy: LIBERTY_INTERPRETER_FEATURE_CALL
191      do
192         dummy := do_precursor(a_precursor, actuals, a_position)
193      end
194
195   item_precursor (a_precursor: LIBERTY_FEATURE; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
196      local
197         call: LIBERTY_INTERPRETER_FEATURE_CALL
198      do
199         call := do_precursor(a_precursor, actuals, a_position)
200         Result := call.returned_object
201      end
202
203   default_object (type: LIBERTY_ACTUAL_TYPE; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
204      do
205         ensure_built(type)
206         if type.is_expanded then
207            Result := new_object(type, a_position)
208         elseif type.is_separate then
209            not_yet_implemented
210         else
211            Result := void_object(type, a_position)
212         end
213      end
214
215   void_object (type: LIBERTY_KNOWN_TYPE; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
216      require
217         not type.is_expanded
218      do
219         create {LIBERTY_INTERPRETER_VOID} Result.make(Current, type, a_position)
220      end
221
222   new_object (object_type: LIBERTY_ACTUAL_TYPE; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
223      do
224         ensure_built(object_type)
225         if object_type.is_deferred then
226            fatal_error("Type " + object_type.full_name + " is deferred. Cannot create an instance of that class.", a_position)
227         end
228         debug ("interpreter.creation")
229            std_output.put_string(once "Creating new object of type ")
230            std_output.put_line(object_type.full_name)
231         end
232         Result := creator.new_object(object_type, a_position)
233      end
234
235   new_array (type: LIBERTY_ACTUAL_TYPE; capacity: INTEGER; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_NATIVE_ARRAY is
236      do
237         check
238            type.parameters.count = 1
239         end
240         ensure_built(type)
241         debug ("interpreter.creation")
242            std_output.put_string(once "Creating new array of ")
243            std_output.put_integer(capacity)
244            std_output.put_character(' ')
245            std_output.put_line(type.parameters.first.full_name)
246         end
247         Result := array_creator.new_array(type, capacity, a_position)
248      end
249
250   array_from_external (type: LIBERTY_ACTUAL_TYPE; capacity: INTEGER; elements: POINTER; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_NATIVE_ARRAY is
251      do
252         check
253            type.parameters.count = 1
254         end
255         ensure_built(type)
256         debug ("interpreter.creation")
257            std_output.put_string(once "Creating new array of ")
258            std_output.put_string(type.parameters.first.full_name)
259            std_output.put_line(once " from external")
260         end
261         Result := array_creator.from_external(type, capacity, elements, a_position)
262      end
263
264   new_string (manifest: STRING; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
265      local
266         the_new_string: LIBERTY_INTERPRETER_OBJECT_STRUCTURE
267         new_string_capacity, new_string_count: LIBERTY_INTERPRETER_OBJECT
268         new_string_storage: LIBERTY_INTERPRETER_NATIVE_ARRAY_TYPED[CHARACTER]
269      do
270         ensure_built(native_array_of_character)
271         ensure_built(universe.type_string)
272
273         debug ("interpreter.creation")
274            std_output.put_string(once "Creating manifest string: ")
275            std_output.put_line(manifest)
276         end
277
278         new_string_capacity := new_integer(manifest.capacity, a_position)
279         new_string_count := new_integer(manifest.count, a_position)
280         create new_string_storage.with_storage(Current, native_array_of_character, universe.type_character, manifest, manifest.capacity, a_position)
281
282         the_new_string ::= creator.new_object(universe.type_string, a_position)
283         the_new_string.put_attribute(capacity_name, new_string_capacity)
284         the_new_string.put_attribute(count_name, new_string_count)
285         the_new_string.put_attribute(storage_name, new_string_storage)
286
287         Result := the_new_string
288      end
289
290   new_boolean (manifest: BOOLEAN; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_BOOLEAN is
291      do
292         ensure_built(universe.type_boolean)
293         create Result.with_item(Current, universe.type_boolean, manifest, a_position)
294      end
295
296   new_integer_64 (manifest: INTEGER_64; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[INTEGER_64] is
297      do
298         ensure_built(universe.type_integer_64)
299         create Result.with_item(Current, universe.type_integer_64, manifest, a_position)
300      end
301
302   new_integer_32 (manifest: INTEGER_32; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[INTEGER_64] is
303      do
304         ensure_built(universe.type_integer_32)
305         create Result.with_item(Current, universe.type_integer_32, manifest, a_position)
306      end
307
308   new_integer (manifest: INTEGER; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[INTEGER_64] is
309      do
310         ensure_built(universe.type_integer)
311         create Result.with_item(Current, universe.type_integer, manifest, a_position)
312      end
313
314   new_integer_16 (manifest: INTEGER_16; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[INTEGER_64] is
315      do
316         ensure_built(universe.type_integer_16)
317         create Result.with_item(Current, universe.type_integer_16, manifest, a_position)
318      end
319
320   new_integer_8 (manifest: INTEGER_8; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[INTEGER_64] is
321      do
322         ensure_built(universe.type_integer_8)
323         create Result.with_item(Current, universe.type_integer_8, manifest, a_position)
324      end
325
326   new_typed_integer (actual_type: LIBERTY_ACTUAL_TYPE; manifest: INTEGER_64; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
327      local
328         i8: INTEGER_8; i16: INTEGER_16; i32: INTEGER_32
329         manifest_type: LIBERTY_ACTUAL_TYPE
330      do
331         ensure_built(actual_type)
332
333         if manifest.fit_integer_8 then
334            i8 := manifest.to_integer_8
335            manifest_type := universe.type_integer_8
336            Result := new_integer_8(i8, a_position)
337         elseif manifest.fit_integer_16 then
338            i16 := manifest.to_integer_16
339            manifest_type := universe.type_integer_16
340            Result := new_integer_16(i16, a_position)
341         elseif manifest.fit_integer_32 then
342            i32 := manifest.to_integer_32
343            manifest_type := universe.type_integer_32
344            Result := new_integer_32(i32, a_position)
345         else
346            manifest_type := universe.type_integer_64
347            Result := new_integer_64(manifest, a_position)
348         end
349
350         check
351            not manifest_type.is_conform_to(actual_type)
352         end
353
354         if manifest_type.converts_to(actual_type) then
355            Result := object_converter.convert_object(Result, actual_type)
356         else
357            fatal_error("Type " + manifest_type.full_name + " does not convert to " + actual_type.full_name, a_position)
358         end
359      ensure
360         Result.result_type = actual_type
361      end
362
363   new_real (manifest: REAL; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[REAL_128] is
364      do
365         ensure_built(universe.type_real)
366         create Result.with_item(Current, universe.type_real, manifest, a_position)
367      end
368
369   new_real_128 (manifest: REAL_128; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[REAL_128] is
370      do
371         ensure_built(universe.type_real_128)
372         create Result.with_item(Current, universe.type_real_128, manifest, a_position)
373      end
374
375   new_real_80 (manifest: REAL_80; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[REAL_128] is
376      do
377         ensure_built(universe.type_real_80)
378         create Result.with_item(Current, universe.type_real_80, manifest, a_position)
379      end
380
381   new_real_64 (manifest: REAL_64; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[REAL_128] is
382      do
383         ensure_built(universe.type_real_64)
384         create Result.with_item(Current, universe.type_real_64, manifest, a_position)
385      end
386
387   new_real_32 (manifest: REAL_32; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[REAL_128] is
388      do
389         ensure_built(universe.type_real_32)
390         create Result.with_item(Current, universe.type_real_32, manifest, a_position)
391      end
392
393   new_character (manifest: CHARACTER; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[CHARACTER] is
394      do
395         ensure_built(universe.type_character)
396         create Result.with_item(Current, universe.type_character, manifest, a_position)
397      end
398
399   new_pointer (manifest: POINTER; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT_HASHABLE[POINTER] is
400      do
401         ensure_built(universe.type_pointer)
402         create Result.with_item(Current, universe.type_pointer, manifest, a_position)
403      end
404
405   new_agent (a_agent: LIBERTY_AGENT): LIBERTY_INTERPRETER_AGENT is
406      local
407         agent_type: LIBERTY_ACTUAL_TYPE
408         arguments: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT]
409         actuals: TRAVERSABLE[LIBERTY_EXPRESSION]
410         i: INTEGER
411      do
412         actuals := a_agent.call.actuals
413         create arguments.with_capacity(actuals.count)
414         from
415            i := actuals.lower
416         until
417            i > actuals.upper
418         loop
419            actuals.item(i).accept(expressions)
420            arguments.add_last(expressions.eval_as_right_value)
421            i := i + 1
422         end
423         agent_type ::= a_agent.result_type.known_type
424         ensure_built(agent_type)
425         Result ::= new_object(agent_type, a_agent.position)
426         Result.set_call(target, a_agent.call, arguments)
427      end
428
429   new_tuple (a_tuple: LIBERTY_TUPLE): LIBERTY_INTERPRETER_TUPLE is
430      local
431         tuple_type: LIBERTY_ACTUAL_TYPE
432      do
433         tuple_type ::= a_tuple.result_type.known_type
434         ensure_built(tuple_type)
435         Result ::= new_object(tuple_type, a_tuple.position)
436      end
437
438   old_value (a_expression: LIBERTY_EXPRESSION): LIBERTY_INTERPRETER_OBJECT is
439      local
440         actual_type: LIBERTY_ACTUAL_TYPE
441      do
442         if current_feature.has_old_value(a_expression) then
443            Result := current_feature.old_value(a_expression)
444         elseif gathering_old_values then
445            actual_type ::= a_expression.result_type.known_type -- I dare anyone to write "old Void"
446            Result := default_object(actual_type, a_expression.position)
447         else
448            fatal_error("Missing old value!!!", a_expression.position)
449         end
450      end
451
452feature {LIBERTY_INTERPRETER_DEBUGGER_VISITOR_IMPL}
453   debug_step (number_of_steps: INTEGER) is
454      require
455         number_of_steps > 0
456      do
457         debugger.steps.after(number_of_steps)
458      end
459
460   debug_step_in is
461      do
462         debugger.steps.at_call_entry
463      end
464
465   debug_step_out is
466      do
467         debugger.steps.at_call_exit
468      end
469
470   set_current_frame (f: like current_frame) is
471      require
472         f.in_range(frame_lower, frame_upper)
473      do
474         current_frame := f
475      ensure
476         current_frame = f
477      end
478
479feature {LIBERTY_INTERPRETER_POSTCONDITION_BROWSER}
480   start_gathering_old_values is
481      do
482         gathering_old_values_counter := gathering_old_values_counter + 1
483      ensure
484         gathering_old_values
485         gathering_old_values_counter = old gathering_old_values_counter + 1
486      end
487
488   finished_gathering_old_values is
489      require
490         gathering_old_values
491      do
492         gathering_old_values_counter := gathering_old_values_counter - 1
493      ensure
494         gathering_old_values_counter = old gathering_old_values_counter - 1
495      end
496
497   has_old_value (a_expression: LIBERTY_EXPRESSION): BOOLEAN is
498      do
499         Result := current_feature.has_old_value(a_expression)
500      end
501
502   start_evaluating_old_value is
503      require
504         gathering_old_values
505      do
506         evaluating_old_value_stack.add_last(current_feature)
507      ensure
508         gathering_old_values_counter = old gathering_old_values_counter
509         evaluating_old_value
510      end
511
512   add_old_value (a_expression: LIBERTY_EXPRESSION; a_value: LIBERTY_INTERPRETER_OBJECT) is
513      require
514         gathering_old_values
515         evaluating_old_value
516         not has_old_value(a_expression)
517      do
518         check
519            evaluating_old_value_stack.last = current_feature
520         end
521         current_feature.add_old_value(a_expression, a_value, old_fatal_error, old_fatal_position)
522         evaluating_old_value_stack.remove_last
523         if evaluating_old_value_stack.is_empty then
524            old_fatal_error := Void
525         end
526      ensure
527         gathering_old_values
528      end
529
530   evaluating_old_value: BOOLEAN is
531      do
532         Result := not evaluating_old_value_stack.is_empty
533      end
534
535feature {}
536   old_fatal_error: FIXED_STRING
537   old_fatal_position: LIBERTY_POSITION
538
539   gathering_old_values_counter: INTEGER
540   evaluating_old_value_stack: COLLECTION[LIBERTY_INTERPRETER_FEATURE_CALL]
541
542feature {}
543   do_call (a_target: LIBERTY_INTERPRETER_OBJECT; feature_to_call: LIBERTY_FEATURE_DEFINITION; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_FEATURE_CALL is
544      do
545         create Result.make(Current, a_target, feature_to_call, actuals, a_position)
546         debug ("interpreter.call")
547            std_output.put_new_line
548            std_output.put_line(once "----------------------------------------------------------------------")
549            std_output.put_integer(call_stack.count)
550            std_output.put_string(once " - Calling ")
551            Result.show_stack(std_output)
552         end
553         debugger.steps.step
554         call_stack.add_last(Result)
555         current_frame := frame_upper
556         Result.call(debugger.steps)
557         check
558            current_feature = Result
559         end
560         call_stack.remove_last
561         current_frame := frame_upper
562         debug ("interpreter.call")
563            std_output.put_integer(call_stack.count)
564            std_output.put_string(once " - Returning from ")
565            Result.show_stack(std_output)
566            std_output.put_line(once "----------------------------------------------------------------------")
567            std_output.put_new_line
568         end
569      end
570
571   do_precursor (a_feature: LIBERTY_FEATURE; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; a_position: LIBERTY_POSITION): LIBERTY_INTERPRETER_FEATURE_CALL is
572      do
573         create Result.make_precursor(Current, current_feature.target, a_feature, actuals, a_position)
574         debug ("interpreter.call")
575            std_output.put_new_line
576            std_output.put_line(once "----------------------------------------------------------------------")
577            std_output.put_integer(call_stack.count)
578            std_output.put_string(once " - Calling precursor feature ")
579            std_output.put_line(Result.name)
580         end
581         debugger.steps.step
582         call_stack.add_last(Result)
583         current_frame := frame_upper
584         Result.call(debugger.steps)
585         check
586            current_feature = Result
587         end
588         call_stack.remove_last
589         current_frame := frame_upper
590         debug ("interpreter.call")
591            std_output.put_integer(call_stack.count)
592            std_output.put_string(once " - Returning from precursor feature ")
593            std_output.put_line(Result.name)
594            if Result.returned_static_type /= Void then
595               std_output.put_string(once "Result = ")
596               object_printer.print_object(std_output, Result.returned_object, 0)
597            end
598            std_output.put_line(once "----------------------------------------------------------------------")
599            std_output.put_new_line
600         end
601      end
602
603feature {LIBERTY_INTERPRETER_FEATURE_CALL}
604   set_evaluating_parameters (cf: like current_feature) is
605      require
606         cf /= Void
607         not is_evaluating_parameters(cf)
608      do
609         check cf = current_feature end
610         feature_evaluating_parameters.add_last(cf)
611         call_stack.remove_last
612         current_frame := frame_upper
613         debug ("interpreter.internals")
614            std_output.put_string(once " {{{ opening parameters evaluation of ")
615            std_output.put_line(cf.name)
616         end
617      ensure
618         is_evaluating_parameters(cf)
619      end
620
621   unset_evaluating_parameters (cf: like current_feature) is
622      require
623         cf /= Void
624         is_evaluating_parameters(cf)
625      do
626         check cf = feature_evaluating_parameters.last end
627         call_stack.add_last(cf)
628         current_frame := frame_upper
629         feature_evaluating_parameters.remove_last
630         debug ("interpreter.internals")
631            std_output.put_string(once " }}} closing parameters evaluation of ")
632            std_output.put_line(cf.name)
633         end
634      ensure
635         not is_evaluating_parameters(cf)
636      end
637
638   is_evaluating_parameters (cf: like current_feature): BOOLEAN is
639      require
640         cf /= Void
641      do
642         Result := not feature_evaluating_parameters.is_empty and then feature_evaluating_parameters.last = cf
643         check
644            Result = feature_evaluating_parameters.fast_has(cf)
645         end
646      end
647
648feature {}
649   feature_evaluating_parameters: COLLECTION[LIBERTY_INTERPRETER_FEATURE_CALL]
650
651   current_feature: LIBERTY_INTERPRETER_FEATURE_CALL is
652      do
653         Result := call_stack.last
654      end
655
656   debug_value (tag, name, op: ABSTRACT_STRING; value: LIBERTY_INTERPRETER_OBJECT) is
657      do
658         std_output.put_string(" **** {")
659         std_output.put_string(current_feature.definition_type.full_name)
660         std_output.put_string(once "}.")
661         std_output.put_string(current_feature.name)
662         std_output.put_string(once ": ")
663         std_output.put_string(tag)
664         std_output.put_string(name)
665         std_output.put_string(op)
666         object_printer.print_object(std_output, value, 2)
667      end
668
669feature {LIBERTY_INTERPRETER_DEBUGGER, LIBERTY_INTERPRETER_EXPRESSIONS, LIBERTY_INTERPRETER_INSTRUCTIONS}
670   target: LIBERTY_INTERPRETER_OBJECT is
671      do
672         Result := current_feature.target
673         debug ("interpreter.internals")
674            debug_value(once "Current", once "", once " is ", Result)
675         end
676      end
677
678   local_value (name: FIXED_STRING): LIBERTY_INTERPRETER_OBJECT is
679      do
680         Result := current_feature.local_value(name)
681         debug ("interpreter.internals")
682            debug_value(once "Local ", name, once " is ", Result)
683         end
684      end
685
686   returned_object: LIBERTY_INTERPRETER_OBJECT is
687      do
688         Result := current_feature.returned_object
689         debug ("interpreter.internals")
690            debug_value(once "Result", once "", once " is ", Result)
691         end
692      end
693
694   writable_feature (name: LIBERTY_FEATURE_NAME): LIBERTY_INTERPRETER_OBJECT is
695      do
696         Result := current_feature.writable_feature(name)
697         debug ("interpreter.internals")
698            debug_value(once "Writable feature ", name.full_name, once " is ", Result)
699         end
700      end
701
702   parameter (name: FIXED_STRING): LIBERTY_INTERPRETER_OBJECT is
703      do
704         Result := current_feature.parameter(name)
705         debug ("interpreter.internals")
706            debug_value(once "Parameter ", name, once " is ", Result)
707         end
708      end
709
710feature {LIBERTY_INTERPRETER_ASSIGNMENT}
711   local_static_type (name: FIXED_STRING): LIBERTY_ACTUAL_TYPE is
712      do
713         Result := current_feature.local_static_type(name)
714      end
715
716   set_local_value (name: FIXED_STRING; value: LIBERTY_INTERPRETER_OBJECT) is
717      do
718         current_feature.set_local_value(name, value)
719         debug ("interpreter.internals")
720            debug_value(once "Local ", name, once " := ", value)
721         end
722      end
723
724   returned_static_type: LIBERTY_ACTUAL_TYPE is
725      do
726         Result := current_feature.returned_static_type
727      end
728
729   set_returned_object (value: LIBERTY_INTERPRETER_OBJECT) is
730      do
731         current_feature.set_returned_object(value)
732         debug ("interpreter.internals")
733            debug_value(once "Result", once "", once " := ", value)
734         end
735      end
736
737   writable_feature_static_type (name: LIBERTY_FEATURE_NAME): LIBERTY_ACTUAL_TYPE is
738      do
739         Result := current_feature.writable_feature_static_type(name)
740      end
741
742   set_writable_feature (name: LIBERTY_FEATURE_NAME; value: LIBERTY_INTERPRETER_OBJECT) is
743      do
744         current_feature.set_writable_feature(name, value)
745         debug ("interpreter.internals")
746            debug_value(once "Writable feature ", name.full_name, once " := ", value)
747         end
748      end
749
750feature {LIBERTY_INTERPRETER_ASSERTION_CHECKER}
751   evaluate_feature_parameters is
752      do
753         current_feature.evaluate_parameters
754      end
755
756feature {}
757   make (a_universe: like universe; a_root_type: like root_type; a_root_feature_name: like root_feature_name) is
758      require
759         a_universe /= Void
760      do
761         universe := a_universe
762
763         root_type := a_root_type
764         root_feature_name := a_root_feature_name
765
766         ensure_built(a_root_type)
767         if not a_root_type.has_feature(a_root_feature_name) then
768            std_error.put_string("Unknown feature ")
769            std_error.put_string(a_root_feature_name.full_name)
770            std_error.put_string(" in type ")
771            std_error.put_line(a_root_type.full_name)
772            die_with_code(1)
773         end
774         root_feature := a_root_type.feature_definition(a_root_feature_name)
775
776         create instructions.make(Current)
777         create expressions_memory.make(Current)
778         create postcondition_browser.make(Current)
779         create assertions.make(Current)
780         create creator.make(Current)
781         create array_creator.make(Current)
782         create builtins.make(Current)
783         create plugins.make(Current)
784         create object_printer.make(Current)
785         create object_converter.make(Current)
786         create debugger.make(Current)
787
788         create {FAST_ARRAY[LIBERTY_INTERPRETER_FEATURE_CALL]} call_stack.with_capacity(1024)
789         create {FAST_ARRAY[LIBERTY_INTERPRETER_FEATURE_CALL]} feature_evaluating_parameters.with_capacity(16)
790         create {FAST_ARRAY[LIBERTY_INTERPRETER_FEATURE_CALL]} evaluating_old_value_stack.with_capacity(2)
791         native_array_of_character := universe.type_native_array({FAST_ARRAY[LIBERTY_ACTUAL_TYPE] << universe.type_character >> }, errors.unknown_position)
792      ensure
793         universe = a_universe
794         root_type = a_root_type
795         root_feature_name = a_root_feature_name
796         root_feature = a_root_type.feature_definition(a_root_feature_name)
797      end
798
799   native_array_of_character: LIBERTY_ACTUAL_TYPE
800
801   root_feature_actuals: COLLECTION[LIBERTY_EXPRESSION] is
802      once
803         create {FAST_ARRAY[LIBERTY_EXPRESSION]} Result.with_capacity(0)
804      ensure
805         Result.is_empty
806      end
807
808   call_stack: COLLECTION[LIBERTY_INTERPRETER_FEATURE_CALL]
809
810   capacity_name: FIXED_STRING is
811      once
812         Result := "capacity".intern
813      end
814
815   count_name: FIXED_STRING is
816      once
817         Result := "count".intern
818      end
819
820   storage_name: FIXED_STRING is
821      once
822         Result := "storage".intern
823      end
824
825   readline: READLINE_INPUT_STREAM is
826      once
827         create Result.make
828      end
829
830   errors: LIBERTY_ERRORS
831
832invariant
833   instructions /= Void
834   expressions_memory /= Void
835   assertions /= Void
836   creator /= Void
837   call_stack /= Void
838   universe /= Void
839   native_array_of_character /= Void
840   feature_evaluating_parameters /= Void
841   evaluating_old_value_stack /= Void
842   postcondition_browser /= Void
843   debugger /= Void
844
845end -- class LIBERTY_INTERPRETER