PageRenderTime 23ms CodeModel.GetById 14ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/interpreter/liberty_interpreter_instructions.e

http://github.com/tybor/Liberty
Specman e | 341 lines | 297 code | 29 blank | 15 comment | 20 complexity | 5e7b80db989f8a968694baba23f3c2f2 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_INSTRUCTIONS
 16
 17inherit
 18   LIBERTY_INSTRUCTION_VISITOR
 19   LIBERTY_VARIANT_VISITOR
 20
 21creation {LIBERTY_INTERPRETER}
 22   make
 23
 24feature {LIBERTY_ASSIGNMENT_ATTEMPT}
 25   visit_liberty_assignment_attempt (v: LIBERTY_ASSIGNMENT_ATTEMPT) is
 26      local
 27         assignment: LIBERTY_INTERPRETER_ASSIGNMENT
 28      do
 29         v.expression.accept(interpreter.expressions)
 30         create assignment.attempt(interpreter, interpreter.expressions.eval_as_right_value)
 31         v.writable.accept(assignment)
 32      end
 33
 34feature {LIBERTY_ASSIGNMENT_FORCED}
 35   visit_liberty_assignment_forced (v: LIBERTY_ASSIGNMENT_FORCED) is
 36      local
 37         assignment: LIBERTY_INTERPRETER_ASSIGNMENT
 38      do
 39         v.expression.accept(interpreter.expressions)
 40         create assignment.forced(interpreter, interpreter.expressions.eval_as_right_value)
 41         v.writable.accept(assignment)
 42      end
 43
 44feature {LIBERTY_ASSIGNMENT_REGULAR}
 45   visit_liberty_assignment_regular (v: LIBERTY_ASSIGNMENT_REGULAR) is
 46      local
 47         assignment: LIBERTY_INTERPRETER_ASSIGNMENT
 48      do
 49         v.expression.accept(interpreter.expressions)
 50         create assignment.regular(interpreter, interpreter.expressions.eval_as_right_value)
 51         v.writable.accept(assignment)
 52      end
 53
 54feature {LIBERTY_CALL_INSTRUCTION}
 55   visit_liberty_call_instruction (v: LIBERTY_CALL_INSTRUCTION) is
 56      local
 57         target: LIBERTY_INTERPRETER_OBJECT
 58         target_type: LIBERTY_ACTUAL_TYPE
 59      do
 60         target_type ::= v.entity.target_type.known_type
 61         interpreter.ensure_built(target_type)
 62         if v.is_implicit_current then
 63            interpreter.call_feature(interpreter.target, v.entity.feature_definition, v.actuals, v.position)
 64         else
 65            v.target.accept(interpreter.expressions)
 66            target := interpreter.expressions.eval_as_target
 67            interpreter.call_feature(target, v.entity.feature_definition, v.actuals, v.position)
 68         end
 69      end
 70
 71feature {LIBERTY_CHECK_INSTRUCTION}
 72   visit_liberty_check_instruction (v: LIBERTY_CHECK_INSTRUCTION) is
 73      do
 74         interpreter.assertions.validate(v.checks, once "Check")
 75      end
 76
 77feature {LIBERTY_COMPOUND}
 78   visit_liberty_compound (v: LIBERTY_COMPOUND) is
 79      local
 80         i: INTEGER
 81      do
 82         from
 83            i := v.lower
 84         until
 85            i > v.upper
 86         loop
 87            v.item(i).accept(Current)
 88            i := i + 1
 89         end
 90      end
 91
 92feature {LIBERTY_CONDITIONAL}
 93   visit_liberty_conditional (v: LIBERTY_CONDITIONAL) is
 94      local
 95         i: INTEGER
 96      do
 97         condition_stack.add_last(False)
 98         from
 99            i := v.conditions.lower
100         until
101            condition_stack.last or else i > v.conditions.upper
102         loop
103            v.conditions.item(i).accept(Current)
104            i := i + 1
105         end
106
107         if not condition_stack.last and then v.else_clause /= Void then
108            v.else_clause.accept(Current)
109         end
110         condition_stack.remove_last
111      ensure
112         condition_stack.count = old condition_stack.count
113      end
114
115feature {LIBERTY_CONDITION}
116   visit_liberty_condition (v: LIBERTY_CONDITION) is
117      local
118         c: LIBERTY_INTERPRETER_OBJECT_NATIVE[BOOLEAN]
119      do
120         v.expression.accept(interpreter.expressions)
121         c ::= interpreter.expressions.eval_memory
122         if c.item then
123            v.instruction.accept(Current)
124            condition_stack.put(True, condition_stack.upper)
125         end
126      ensure
127         condition_stack.count = old condition_stack.count
128      end
129
130feature {LIBERTY_CREATION_INSTRUCTION}
131   visit_liberty_creation_instruction (v: LIBERTY_CREATION_INSTRUCTION) is
132      local
133         assignment: LIBERTY_INTERPRETER_ASSIGNMENT
134         new_object: LIBERTY_INTERPRETER_OBJECT
135         actual_type: LIBERTY_ACTUAL_TYPE
136      do
137         actual_type ::= v.type.known_type
138         new_object := interpreter.new_object(actual_type, v.position)
139         interpreter.call_feature(new_object, v.feature_entity.feature_definition, v.feature_arguments, v.position)
140         create assignment.regular(interpreter, new_object)
141         v.writable.accept(assignment)
142      end
143
144feature {LIBERTY_DEBUG}
145   visit_liberty_debug (v: LIBERTY_DEBUG) is
146      do
147         if options.debug_enabled then --| TODO: use v.keys
148            v.instruction.accept(Current)
149         end
150      end
151
152feature {LIBERTY_DEFAULT}
153   visit_liberty_default (v: LIBERTY_DEFAULT) is
154      do
155         v.instruction.accept(Current)
156      end
157
158feature {LIBERTY_EMPTY}
159   visit_liberty_empty (v: LIBERTY_EMPTY) is
160      do
161         -- well, nothing
162      end
163
164feature {LIBERTY_INSPECT}
165   visit_liberty_inspect (v: LIBERTY_INSPECT) is
166      local
167         exp: LIBERTY_INTERPRETER_OBJECT
168         i, n: INTEGER
169      do
170         v.expression.accept(interpreter.expressions)
171         exp := interpreter.expressions.eval_as_right_value
172         inspect_stack.add_last(exp)
173         n := inspect_stack.count
174         from
175            i := v.clauses.lower
176         until
177            inspect_stack.count < n or else i > v.clauses.upper
178         loop
179            v.clauses.item(i).accept(Current)
180            i := i + 1
181         end
182         if inspect_stack.count = n then
183            if v.else_clause = Void then
184               interpreter.fatal_error("Inspect: nothing selected", v.position)
185            else
186               v.else_clause.accept(Current)
187               check
188                  inspect_stack.last = exp
189               end
190               inspect_stack.remove_last
191            end
192         else
193            check
194               inspect_stack.count = n - 1
195            end
196         end
197      ensure
198         inspect_stack.count = old inspect_stack.count
199      end
200
201feature {LIBERTY_INSPECT_CLAUSE}
202   visit_liberty_inspect_clause (v: LIBERTY_INSPECT_CLAUSE) is
203      local
204         i, n: INTEGER; found: BOOLEAN
205      do
206         from
207            n := inspect_stack.count
208            i := v.values.lower
209         until
210            found or else i > v.values.upper
211         loop
212            v.values.item(i).accept(Current)
213            if inspect_stack.count < n then
214               check
215                  inspect_stack.count = n - 1
216               end
217               v.instruction.accept(Current)
218               found := True
219            end
220            i := i + 1
221         end
222      ensure
223         inspect_stack.count.in_range(old inspect_stack.count - 1, old inspect_stack.count)
224      end
225
226feature {LIBERTY_INSPECT_SLICE}
227   visit_liberty_inspect_slice (v: LIBERTY_INSPECT_SLICE) is
228      local
229         lower, upper: LIBERTY_INTERPRETER_OBJECT
230      do
231         v.lower.accept(interpreter.expressions)
232         lower := interpreter.expressions.eval_as_right_value
233         if v.lower = v.upper then
234            if inspect_stack.last.is_equal(lower) then
235               inspect_stack.remove_last
236            end
237         else
238            v.upper.accept(interpreter.expressions)
239            upper := interpreter.expressions.eval_as_right_value
240            if inspect_stack.last.is_between(lower, upper, v.position) then
241               inspect_stack.remove_last
242            end
243         end
244      ensure
245         inspect_stack.count.in_range(old inspect_stack.count - 1, old inspect_stack.count)
246      end
247
248feature {LIBERTY_LOOP}
249   visit_liberty_loop (v: LIBERTY_LOOP) is
250      local
251         exp_until: LIBERTY_INTERPRETER_OBJECT_NATIVE[BOOLEAN]
252         done, check_invariant, check_variant: BOOLEAN
253      do
254         check_invariant := options.is_invariant_checked
255         check_variant := v.variant_clause /= Void and then options.is_all_checked
256
257         from
258            v.init.accept(Current)
259            if check_variant then
260               loop_variant_stack.add_last(Void)
261            end
262         until
263            done
264         loop
265            if check_invariant then
266               v.invariant_clause.accept(interpreter.assertions)
267            end
268            v.expression.accept(interpreter.expressions)
269            exp_until ::= interpreter.expressions.eval_as_right_value
270            if exp_until.item then
271               done := True
272            else
273               if check_variant then
274                  v.variant_clause.accept(Current)
275               end
276               v.body.accept(Current)
277            end
278         end
279         if check_variant then
280            loop_variant_stack.remove_last
281         end
282      end
283
284feature {LIBERTY_VARIANT}
285   visit_liberty_variant (v: LIBERTY_VARIANT) is
286      local
287         exp_variant: LIBERTY_INTERPRETER_OBJECT_NATIVE[INTEGER_64]
288      do
289         v.expression.accept(interpreter.expressions)
290         exp_variant ::= interpreter.expressions.eval_as_right_value
291         if loop_variant_stack.last = Void then
292            loop_variant_stack.put(exp_variant, loop_variant_stack.upper)
293         elseif exp_variant.item >= loop_variant_stack.last.item then
294            interpreter.fatal_error("Variant failed: was " + loop_variant_stack.last.item.out
295                                    + ", now " + exp_variant.item.out, v.expression.position)
296         else
297            loop_variant_stack.put(exp_variant, loop_variant_stack.upper)
298         end
299      end
300
301feature {LIBERTY_PRECURSOR_INSTRUCTION}
302   visit_liberty_precursor_instruction (v: LIBERTY_PRECURSOR_INSTRUCTION) is
303      do
304         interpreter.call_precursor(v.the_feature, v.actuals, v.position)
305      end
306
307feature {LIBERTY_RETRY}
308   visit_liberty_retry (v: LIBERTY_RETRY) is
309      do
310         not_yet_implemented
311      end
312
313feature {}
314   make (a_interpreter: like interpreter) is
315      require
316         a_interpreter /= Void
317      do
318         interpreter := a_interpreter
319         create condition_stack.with_capacity(0)
320         create inspect_stack.with_capacity(0)
321         if options.is_all_checked then
322            create loop_variant_stack.with_capacity(0)
323         end
324      ensure
325         interpreter = a_interpreter
326      end
327
328   interpreter: LIBERTY_INTERPRETER
329
330   condition_stack: FAST_ARRAY[BOOLEAN]
331   inspect_stack: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT]
332   loop_variant_stack: FAST_ARRAY[LIBERTY_INTERPRETER_OBJECT_NATIVE[INTEGER_64]]
333
334   options: LIBERTY_INTERPRETER_OPTIONS
335
336invariant
337   interpreter /= Void
338   condition_stack /= Void
339   options.is_all_checked implies loop_variant_stack /= Void
340
341end -- class LIBERTY_INTERPRETER_INSTRUCTIONS