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