PageRenderTime 585ms CodeModel.GetById 8ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 562ms

/src/tools/interpreter/liberty_interpreter_expressions.e

http://github.com/tybor/Liberty
Specman e | 708 lines | 593 code | 78 blank | 37 comment | 11 complexity | d2a3b967f99549fd49ec0e642f83fa3d 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_EXPRESSIONS
 16
 17inherit
 18   LIBERTY_EXPRESSION_VISITOR
 19   LIBERTY_ENTITY_VISITOR
 20   LIBERTY_INTERPRETER_OBJECT_VISITOR
 21
 22insert
 23   LIBERTY_ARRAY_MANIFEST_CONSTANTS
 24
 25creation {LIBERTY_INTERPRETER}
 26   make
 27
 28feature {ANY}
 29   eval_memory: LIBERTY_INTERPRETER_OBJECT
 30
 31   eval_as_right_value: LIBERTY_INTERPRETER_OBJECT is
 32         -- When `eval_memory' is to be assigned to an entity
 33      do
 34         Result := eval_memory.as_right_value
 35      end
 36
 37   eval_as_target: LIBERTY_INTERPRETER_OBJECT is
 38         -- When `eval_memory' is to be used as a target of a call
 39      do
 40         Result := eval_memory.as_target(eval_memory.position)
 41      end
 42
 43feature {LIBERTY_ADD}
 44   visit_liberty_add (v: LIBERTY_ADD) is
 45      do
 46         visit_infix(v)
 47      end
 48
 49feature {LIBERTY_AGENT}
 50   visit_liberty_agent (v: LIBERTY_AGENT) is
 51      do
 52         eval_memory := interpreter.new_agent(v)
 53      end
 54
 55feature {LIBERTY_AND}
 56   visit_liberty_and (v: LIBERTY_AND) is
 57      do
 58         visit_infix(v)
 59      end
 60
 61feature {LIBERTY_AND_THEN}
 62   visit_liberty_and_then (v: LIBERTY_AND_THEN) is
 63      do
 64         visit_infix(v)
 65      end
 66
 67feature {LIBERTY_ARRAY_MANIFEST}
 68   visit_liberty_array_manifest (v: LIBERTY_ARRAY_MANIFEST) is
 69         -- manifest_make
 70         -- manifest_put
 71         -- manifest_semicolon_check: BOOLEAN or INTEGER
 72      local
 73         semicolons: INTEGER
 74      do
 75         semicolons := semicolon_pattern(v.separators)
 76         if semicolons < 0 then
 77            eval_memory := Void
 78         else
 79            new_array_manifest(semicolons, v)
 80         end
 81      end
 82
 83feature {}
 84   new_array_manifest (semicolons: INTEGER; v: LIBERTY_ARRAY_MANIFEST) is
 85      require
 86         semicolons = semicolon_pattern(v.separators)
 87      local
 88         array_type: LIBERTY_ACTUAL_TYPE
 89         fd: LIBERTY_FEATURE_DEFINITION
 90         new_array: like eval_memory
 91         i, j, index, capacity, n_args: INTEGER
 92         args: FAST_ARRAY[LIBERTY_EXPRESSION]
 93         f: LIBERTY_FEATURE
 94      do
 95         -- NOTE!!
 96         --
 97         -- Liberty does not make use of SmartEiffel's "manifest_semicolon_check" feature.
 98         --
 99         -- Instead, the number of arguments of "manifest_put" is taken into account to determine if
100         -- semi-colons are needed. In a nutshell, they are if manifest_put needs more than one extra argument
101         -- (i.e. besides the 'index' first argument).
102         --
103
104         array_type ::= v.result_type.known_type
105         interpreter.ensure_built(array_type)
106
107         fd := array_type.feature_definition(manifest_make_feature_name)
108         new_array := interpreter.new_object(array_type, v.position)
109         capacity := v.contents.count
110         create args.with_capacity(1 + v.parameters.count)
111         args.add_last(interpreter.new_integer_32(capacity, v.position))
112         args.append_traversable(v.parameters)
113         interpreter.call_feature(new_array, fd, args, v.position)
114
115         fd := array_type.feature_definition(manifest_put_feature_name)
116         f := fd.the_feature.bound(array_type)
117         if f.parameters.count < 2 then
118            -- TODO: error: not enough parameters
119            not_yet_implemented
120         elseif semicolons = 0 and then f.parameters.count = 2 then
121            -- ok, using only commas is allowed if there is only one extra argument
122            n_args := 1
123         elseif f.parameters.count = semicolons + 1 then
124            -- ok, using semi-colon-separated slices; note that semi-colons are also allowed between each
125            -- argument
126            n_args := semicolons
127         elseif f.parameters.count = v.contents.count + 1 then
128            -- ok, special case if there is only one slice that must be given at once to manifest_put
129            n_args := v.contents.count
130         else
131            -- TODO: error: the semicolons pattern does not match the number of arguments of manifest_put + 1
132            not_yet_implemented
133         end
134
135         check
136            n_args.in_range(1, v.contents.count)
137            v.contents.count \\ n_args = 0
138         end
139         from
140            args.with_capacity(n_args + 1)
141            index := 0
142            i := v.contents.lower
143         until
144            i > v.contents.upper
145         loop
146            args.clear_count
147            args.add_last(interpreter.new_integer_32(index, v.position))
148            from
149               j := 0
150            until
151               j = n_args
152            loop
153               v.contents.item(i+j).accept(Current)
154               args.add_last(eval_as_right_value)
155               j := j + 1
156            end
157            interpreter.call_feature(new_array, fd, args, v.position)
158            index := index + 1
159            i := i + n_args
160         end
161
162         eval_memory := new_array
163      end
164
165   semicolon_pattern (separators: TRAVERSABLE[LIBERTY_ARRAY_MANIFEST_SEPARATOR]): INTEGER is
166      local
167         n, i: INTEGER
168      do
169         from
170            i := separators.lower
171            n := 1
172         until
173            Result < 0 or else i > separators.upper
174         loop
175            if separators.item(i) = separator_comma then
176               check
177                  not_last: i < separators.upper
178               end
179               n := n + 1
180            elseif separators.item(i) = separator_semi_colon then
181               check
182                  not_last: i < separators.upper
183               end
184               if Result = 0 then
185                  Result := n
186               elseif Result /= n then
187                  -- TODO: error, non regular semi-colon pattern
188                  not_yet_implemented
189               end
190               n := 1
191            else
192               check
193                  is_none: separators.item(i) = separator_none
194                  is_last: i = separators.upper
195               end
196               if Result /= 0 and then Result /= n then
197                  -- TODO: error, non regular semi-colon pattern
198                  not_yet_implemented
199               end
200            end
201            i := i + 1
202         end
203      ensure
204         Result >= 0
205         Result > 0 implies separators.count \\ Result = 0
206      end
207
208feature {LIBERTY_ASSIGNMENT_TEST}
209   visit_liberty_assignment_test (v: LIBERTY_ASSIGNMENT_TEST) is
210      do
211         v.expression.accept(Current)
212         eval_memory := interpreter.new_boolean(eval_memory.type.is_conform_to(v.tested_type.known_type), v.position)
213      ensure
214         eval_memory /= Void
215      end
216
217feature {LIBERTY_BOOLEAN_MANIFEST}
218   visit_liberty_boolean_manifest (v: LIBERTY_BOOLEAN_MANIFEST) is
219      do
220         eval_memory := interpreter.new_boolean(v.manifest, v.position)
221      ensure
222         eval_memory /= Void
223      end
224
225feature {LIBERTY_CALL_EXPRESSION}
226   visit_liberty_call_expression (v: LIBERTY_CALL_EXPRESSION) is
227      do
228         if v.is_implicit_current then
229            eval_memory := item_feature(interpreter.target, v.entity, v.actuals, v.position)
230         else
231            v.target.accept(Current)
232            eval_memory := item_feature(eval_as_target, v.entity, v.actuals, v.position)
233         end
234      ensure
235         eval_memory /= Void
236      end
237
238feature {LIBERTY_CAST_EXPRESSION}
239   visit_liberty_cast_expression (v: LIBERTY_CAST_EXPRESSION) is
240      local
241         actual_type: LIBERTY_ACTUAL_TYPE
242      do
243         v.expression.accept(Current)
244         actual_type ::= v.result_type.known_type
245         if eval_memory.result_type.known_type.is_conform_to(actual_type) then
246            -- nothing to do
247         elseif eval_memory.result_type.known_type.converts_to(actual_type) then
248            eval_memory := interpreter.object_converter.convert_object(eval_memory, actual_type)
249         else
250            -- fatal error!! should not happen
251            check False end
252            crash
253         end
254      end
255
256feature {LIBERTY_CHARACTER_MANIFEST}
257   visit_liberty_character_manifest (v: LIBERTY_CHARACTER_MANIFEST) is
258      do
259         eval_memory := interpreter.new_character(v.manifest, v.position)
260      ensure
261         eval_memory /= Void
262      end
263
264feature {LIBERTY_CREATION_EXPRESSION}
265   visit_liberty_creation_expression (v: LIBERTY_CREATION_EXPRESSION) is
266      local
267         actual_type: LIBERTY_ACTUAL_TYPE
268      do
269         actual_type ::= v.result_type.known_type
270         eval_memory := interpreter.new_object(actual_type, v.position)
271         interpreter.call_feature(eval_memory, v.feature_entity.feature_definition, v.feature_arguments, v.position)
272      ensure
273         eval_memory /= Void
274      end
275
276feature {LIBERTY_DIVIDE}
277   visit_liberty_divide (v: LIBERTY_DIVIDE) is
278      do
279         visit_infix(v)
280      end
281
282feature {LIBERTY_ENTITY_EXPRESSION}
283   visit_liberty_entity_expression (v: LIBERTY_ENTITY_EXPRESSION) is
284      do
285         v.entity.accept(Current)
286      end
287
288feature {LIBERTY_ENTITY_REFERENCE}
289   visit_liberty_entity_reference (v: LIBERTY_ENTITY_REFERENCE) is
290      do
291         not_yet_implemented
292      end
293
294feature {LIBERTY_EQUALS}
295   visit_liberty_equals (v: LIBERTY_EQUALS) is
296      do
297         eval_memory := interpreter.new_boolean(visit_comparison(v), v.position)
298      ensure
299         eval_memory /= Void
300      end
301
302feature {LIBERTY_GREATER_OR_EQUAL}
303   visit_liberty_greater_or_equal (v: LIBERTY_GREATER_OR_EQUAL) is
304      do
305         visit_infix(v)
306      end
307
308feature {LIBERTY_GREATER_THAN}
309   visit_liberty_greater_than (v: LIBERTY_GREATER_THAN) is
310      do
311         visit_infix(v)
312      end
313
314feature {LIBERTY_IMPLIES}
315   visit_liberty_implies (v: LIBERTY_IMPLIES) is
316      do
317         visit_infix(v)
318      end
319
320feature {LIBERTY_INFIX_OPERATOR}
321   visit_liberty_infix_operator (v: LIBERTY_INFIX_OPERATOR) is
322      do
323         visit_infix(v)
324      end
325
326feature {LIBERTY_INT_DIVIDE}
327   visit_liberty_int_divide (v: LIBERTY_INT_DIVIDE) is
328      do
329         visit_infix(v)
330      end
331
332feature {LIBERTY_INTEGER_16_MANIFEST}
333   visit_liberty_integer_16_manifest (v: LIBERTY_INTEGER_16_MANIFEST) is
334      do
335         eval_memory := interpreter.new_integer_16(v.manifest, v.position)
336      ensure
337         eval_memory /= Void
338      end
339
340feature {LIBERTY_INTEGER_32_MANIFEST}
341   visit_liberty_integer_32_manifest (v: LIBERTY_INTEGER_32_MANIFEST) is
342      do
343         eval_memory := interpreter.new_integer_32(v.manifest, v.position)
344      ensure
345         eval_memory /= Void
346      end
347
348feature {LIBERTY_INTEGER_64_MANIFEST}
349   visit_liberty_integer_64_manifest (v: LIBERTY_INTEGER_64_MANIFEST) is
350      do
351         eval_memory := interpreter.new_integer_64(v.manifest, v.position)
352      ensure
353         eval_memory /= Void
354      end
355
356feature {LIBERTY_INTEGER_8_MANIFEST}
357   visit_liberty_integer_8_manifest (v: LIBERTY_INTEGER_8_MANIFEST) is
358      do
359         eval_memory := interpreter.new_integer_8(v.manifest, v.position)
360      ensure
361         eval_memory /= Void
362      end
363
364feature {LIBERTY_INTEGER_TYPED_MANIFEST}
365   visit_liberty_integer_typed_manifest (v: LIBERTY_INTEGER_TYPED_MANIFEST) is
366      local
367         actual_type: LIBERTY_ACTUAL_TYPE
368      do
369         actual_type ::= v.result_type.known_type
370         eval_memory := interpreter.new_typed_integer(actual_type, v.manifest, v.position)
371      ensure
372         eval_memory /= Void
373      end
374
375feature {LIBERTY_INT_REMAINDER}
376   visit_liberty_int_remainder (v: LIBERTY_INT_REMAINDER) is
377      do
378         visit_infix(v)
379      end
380
381feature {LIBERTY_LESS_OR_EQUAL}
382   visit_liberty_less_or_equal (v: LIBERTY_LESS_OR_EQUAL) is
383      do
384         visit_infix(v)
385      end
386
387feature {LIBERTY_LESS_THAN}
388   visit_liberty_less_than (v: LIBERTY_LESS_THAN) is
389      do
390         visit_infix(v)
391      end
392
393feature {LIBERTY_NEGATIVE}
394   visit_liberty_negative (v: LIBERTY_NEGATIVE) is
395      do
396         visit_prefix(v)
397      end
398
399feature {LIBERTY_NOT}
400   visit_liberty_not (v: LIBERTY_NOT) is
401      do
402         visit_prefix(v)
403      end
404
405feature {LIBERTY_NOT_EQUALS}
406   visit_liberty_not_equals (v: LIBERTY_NOT_EQUALS) is
407      do
408         eval_memory := interpreter.new_boolean(not visit_comparison(v), v.position)
409      ensure
410         eval_memory /= Void
411      end
412
413feature {LIBERTY_OLD}
414   visit_liberty_old (v: LIBERTY_OLD) is
415      do
416         eval_memory := interpreter.old_value(v.expression)
417      ensure
418         eval_memory /= Void
419      end
420
421feature {LIBERTY_OPEN_ARGUMENT}
422   visit_liberty_open_argument (v: LIBERTY_OPEN_ARGUMENT) is
423      local
424         actual_type: LIBERTY_ACTUAL_TYPE
425      do
426         actual_type ::= v.result_type.known_type
427         create {LIBERTY_INTERPRETER_OPEN_ARGUMENT} eval_memory.make(interpreter, actual_type)
428      ensure
429         eval_memory /= Void
430      end
431
432feature {LIBERTY_OR}
433   visit_liberty_or (v: LIBERTY_OR) is
434      do
435         visit_infix(v)
436      end
437
438feature {LIBERTY_OR_ELSE}
439   visit_liberty_or_else (v: LIBERTY_OR_ELSE) is
440      do
441         visit_infix(v)
442      end
443
444feature {LIBERTY_POSITIVE}
445   visit_liberty_positive (v: LIBERTY_POSITIVE) is
446      do
447         visit_prefix(v)
448      end
449
450feature {LIBERTY_POWER}
451   visit_liberty_power (v: LIBERTY_POWER) is
452      do
453         visit_infix(v)
454      end
455
456feature {LIBERTY_PRECURSOR_EXPRESSION}
457   visit_liberty_precursor_expression (v: LIBERTY_PRECURSOR_EXPRESSION) is
458      do
459         eval_memory := interpreter.item_precursor(v.the_feature, v.actuals, v.position)
460      ensure
461         eval_memory /= Void
462      end
463
464feature {LIBERTY_PREFIX_OPERATOR}
465   visit_liberty_prefix_operator (v: LIBERTY_PREFIX_OPERATOR) is
466      do
467         visit_prefix(v)
468      end
469
470feature {LIBERTY_REAL_MANIFEST}
471   visit_liberty_real_manifest (v: LIBERTY_REAL_MANIFEST) is
472      do
473         eval_memory := interpreter.new_real(v.manifest, v.position)
474      ensure
475         eval_memory /= Void
476      end
477
478feature {LIBERTY_REAL_TYPED_MANIFEST}
479   visit_liberty_real_typed_manifest (v: LIBERTY_REAL_TYPED_MANIFEST) is
480      do
481         not_yet_implemented
482      end
483
484feature {LIBERTY_STRING_MANIFEST}
485   visit_liberty_string_manifest (v: LIBERTY_STRING_MANIFEST) is
486      do
487         eval_memory := interpreter.new_string(v.manifest, v.position)
488      ensure
489         eval_memory /= Void
490      end
491
492feature {LIBERTY_STRING_TYPED_MANIFEST}
493   visit_liberty_string_typed_manifest (v: LIBERTY_STRING_TYPED_MANIFEST) is
494      do
495         not_yet_implemented
496      end
497
498feature {LIBERTY_SUBTRACT}
499   visit_liberty_subtract (v: LIBERTY_SUBTRACT) is
500      do
501         visit_infix(v)
502      end
503
504feature {LIBERTY_TIMES}
505   visit_liberty_times (v: LIBERTY_TIMES) is
506      do
507         visit_infix(v)
508      end
509
510feature {LIBERTY_TUPLE}
511   visit_liberty_tuple (v: LIBERTY_TUPLE) is
512      local
513         tuple: LIBERTY_INTERPRETER_TUPLE
514         i: INTEGER
515      do
516         tuple := interpreter.new_tuple(v)
517         tuple.ensure_capacity(v.count)
518         from
519            i := v.lower
520         until
521            i > v.upper
522         loop
523            v.item(i).accept(Current)
524            tuple.add_last(eval_as_right_value)
525            i := i + 1
526         end
527         eval_memory := tuple
528      end
529
530feature {LIBERTY_VOID}
531   visit_liberty_void (v: LIBERTY_VOID) is
532      do
533         eval_memory := interpreter.void_object(v.result_type.known_type, v.position)
534      ensure
535         eval_memory /= Void
536      end
537
538feature {LIBERTY_XOR}
539   visit_liberty_xor (v: LIBERTY_XOR) is
540      do
541         visit_infix(v)
542      end
543
544feature {LIBERTY_CURRENT}
545   visit_liberty_current (v: LIBERTY_CURRENT) is
546      do
547         eval_memory := interpreter.target
548         debug
549            std_output.put_string(once " => Current = ")
550            interpreter.object_printer.print_object(std_output, eval_memory, 2)
551         end
552      ensure
553         eval_memory /= Void
554      end
555
556feature {LIBERTY_FEATURE_DEFINITION}
557   visit_liberty_feature_definition (v: LIBERTY_FEATURE_DEFINITION) is
558      do
559         check False end
560      end
561
562feature {LIBERTY_FEATURE_ENTITY}
563   visit_liberty_feature_entity (v: LIBERTY_FEATURE_ENTITY) is
564      do
565         eval_memory := interpreter.item_feature(interpreter.target, v.feature_definition, no_actuals, v.position)
566         debug
567            std_output.put_string(once " => Attribute ")
568            std_output.put_string(v.name)
569            std_output.put_string(once " = ")
570            interpreter.object_printer.print_object(std_output, eval_memory, 2)
571         end
572      ensure
573         eval_memory /= Void
574      end
575
576feature {LIBERTY_LOCAL}
577   visit_liberty_local (v: LIBERTY_LOCAL) is
578      do
579         eval_memory := interpreter.local_value(v.name)
580         debug
581            std_output.put_string(once " => Local ")
582            std_output.put_string(v.name)
583            std_output.put_string(once " = ")
584            interpreter.object_printer.print_object(std_output, eval_memory, 2)
585         end
586      ensure
587         eval_memory /= Void
588      end
589
590feature {LIBERTY_PARAMETER}
591   visit_liberty_parameter (v: LIBERTY_PARAMETER) is
592      do
593         eval_memory := interpreter.parameter(v.name)
594         debug
595            std_output.put_string(once " => Parameter ")
596            std_output.put_string(v.name)
597            std_output.put_string(once " = ")
598            interpreter.object_printer.print_object(std_output, eval_memory, 2)
599         end
600      ensure
601         eval_memory /= Void
602      end
603
604feature {LIBERTY_RESULT}
605   visit_liberty_result (v: LIBERTY_RESULT) is
606      do
607         eval_memory := interpreter.returned_object
608         debug
609            std_output.put_string(once " => Result = ")
610            interpreter.object_printer.print_object(std_output, eval_memory, 2)
611         end
612      ensure
613         eval_memory /= Void
614      end
615
616feature {LIBERTY_WRITABLE_FEATURE}
617   visit_liberty_writable_feature (v: LIBERTY_WRITABLE_FEATURE) is
618      do
619         check False end
620      end
621
622feature {LIBERTY_INTERPRETER_OBJECT}
623   visit_liberty_object (a_object: LIBERTY_INTERPRETER_OBJECT) is
624      do
625         eval_memory := a_object
626      end
627
628feature {}
629   make (a_interpreter: like interpreter) is
630      require
631         a_interpreter /= Void
632      do
633         interpreter := a_interpreter
634      ensure
635         interpreter = a_interpreter
636      end
637
638   interpreter: LIBERTY_INTERPRETER
639
640feature {}
641   item_feature (target: LIBERTY_INTERPRETER_OBJECT; entity: LIBERTY_FEATURE_ENTITY; actuals: TRAVERSABLE[LIBERTY_EXPRESSION]; position: LIBERTY_POSITION): LIBERTY_INTERPRETER_OBJECT is
642      local
643         target_type: LIBERTY_ACTUAL_TYPE
644      do
645         target_type ::= entity.target_type.known_type
646         interpreter.ensure_built(target_type)
647         if entity.has_feature then
648            Result := interpreter.item_feature(target, entity.feature_definition, actuals, position)
649         else
650            interpreter.fatal_error("Unknown feature " + entity.name + " in type " + target.type.full_name, position)
651         end
652      end
653
654   visit_infix (v: LIBERTY_INFIX_CALL) is
655      do
656         v.target.accept(Current)
657         eval_memory := item_feature(eval_as_target, v.entity, v.actuals, v.position)
658      ensure
659         eval_memory /= Void
660      end
661
662   visit_prefix (v: LIBERTY_PREFIX_CALL) is
663      do
664         v.target.accept(Current)
665         eval_memory := item_feature(eval_as_target, v.entity, no_actuals, v.position)
666      ensure
667         eval_memory /= Void
668      end
669
670   visit_comparison (v: LIBERTY_COMPARISON): BOOLEAN is
671      local
672         left, right: LIBERTY_INTERPRETER_OBJECT
673         left_type, right_type: LIBERTY_ACTUAL_TYPE
674      do
675         v.left.accept(Current)
676         left := eval_as_right_value
677         v.right.accept(Current)
678         right := eval_as_right_value
679         if left.is_void then
680            Result := right.is_void
681         elseif right.is_void then
682            check not Result end
683         else
684            left_type ::= left.type
685            right_type ::= right.type
686            if left_type.is_conform_to(right_type) then
687               Result := left.is_equal(right)
688            elseif right_type.is_conform_to(left_type) then
689               Result := right.is_equal(left)
690            elseif left_type.converts_to(right_type) then
691               Result := interpreter.object_converter.convert_object(left, right_type).is_equal(right)
692            elseif right_type.converts_to(left_type) then
693               Result := interpreter.object_converter.convert_object(right, left_type).is_equal(left)
694            else
695               check not Result end
696            end
697         end
698      end
699
700   no_actuals: TRAVERSABLE[LIBERTY_EXPRESSION] is
701      once
702         create {FAST_ARRAY[LIBERTY_EXPRESSION]} Result.with_capacity(0)
703      end
704
705invariant
706   interpreter /= Void
707
708end -- class LIBERTY_INTERPRETER_EXPRESSIONS