/src/tools/interpreter/liberty_interpreter_debugger.e

http://github.com/tybor/Liberty · Specman e · 210 lines · 170 code · 21 blank · 19 comment · 8 complexity · b5ab9f4d91199f0729e78b0641e7f1d0 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_DEBUGGER
  16. inherit
  17. LIBERTY_INTERPRETER_DEBUGGER_VISITOR
  18. create {LIBERTY_INTERPRETER}
  19. make
  20. feature {LIBERTY_INTERPRETER}
  21. steps: LIBERTY_INTERPRETER_DEBUGGER_STEPS
  22. -- The object to notify about the running program: entry and exit of functions, code stepping...
  23. break (a_entry: like entry): BOOLEAN is
  24. -- `entry' is the debug instructions entered by the user.
  25. --
  26. -- Returns True if the program should continue running, False if the debugger should display the
  27. -- prompt again and wait for further instructions.
  28. require
  29. a_entry /= Void
  30. do
  31. entry.copy(a_entry)
  32. if not entry.is_empty then
  33. if entry.first = ':' then
  34. Result := debug_entry
  35. else
  36. execute
  37. check
  38. not Result
  39. end
  40. end
  41. end
  42. end
  43. feature {}
  44. debug_entry: BOOLEAN is
  45. require
  46. entry.first = ':'
  47. local
  48. evaled: BOOLEAN
  49. do
  50. entry.remove_first
  51. if not entry.is_empty then
  52. parser_buffer.initialize_with(entry)
  53. debug_grammar.reset
  54. evaled := parser.eval(parser_buffer, debug_grammar.table, once "Entry")
  55. if not evaled then
  56. std_error.put_line(once "Incomplete command.")
  57. elseif parser.error /= Void then
  58. errors.emit_syntax_error(parser.error, entry, Void)
  59. else
  60. debug_grammar.root_node.accept(debug_visitor)
  61. Result := debug_visitor.should_continue
  62. end
  63. end
  64. end
  65. execute is
  66. do
  67. check
  68. saved_errors.is_empty
  69. end
  70. if try_to_execute_expression then
  71. elseif try_to_execute_instruction then
  72. else
  73. print_saved_errors
  74. end
  75. saved_errors.clear_count
  76. end
  77. feature {}
  78. try_to_execute_expression: BOOLEAN is
  79. local
  80. ast: LIBERTY_AST_EXPRESSION; exp: LIBERTY_EXPRESSION
  81. actual_type: LIBERTY_ACTUAL_TYPE; done: BOOLEAN
  82. do
  83. error_saved := False
  84. from
  85. until
  86. done
  87. loop
  88. ast := interpreter.universe.parse_expression(entry, agent save_error)
  89. if ast /= Void then
  90. actual_type ::= interpreter.target.result_type.known_type
  91. exp := builder.expression(ast, actual_type)
  92. if exp.result_type /= Void then
  93. exp.accept(interpreter.expressions)
  94. interpreter.object_printer.print_object(std_output, interpreter.expressions.eval_memory, 0)
  95. Result := True
  96. done := True
  97. end
  98. elseif not error_saved then
  99. readline.set_prompt(once " ... > ")
  100. readline.read_line
  101. entry.extend('%N')
  102. entry.append(readline.last_string)
  103. else
  104. done := True
  105. end
  106. end
  107. end
  108. try_to_execute_instruction: BOOLEAN is
  109. local
  110. ast: LIBERTY_AST_INSTRUCTION; ins: LIBERTY_INSTRUCTION
  111. actual_type: LIBERTY_ACTUAL_TYPE; done: BOOLEAN
  112. do
  113. error_saved := False
  114. from
  115. until
  116. done
  117. loop
  118. ast := interpreter.universe.parse_instruction(entry, agent save_error)
  119. if ast /= Void then
  120. actual_type ::= interpreter.target.result_type.known_type
  121. ins := builder.instruction(ast, actual_type)
  122. ins.accept(interpreter.instructions)
  123. Result := True
  124. done := True
  125. elseif not error_saved then
  126. readline.set_prompt(once " ... > ")
  127. readline.read_line
  128. entry.extend('%N')
  129. entry.append(readline.last_string)
  130. else
  131. done := True
  132. end
  133. end
  134. end
  135. entry: STRING is ""
  136. saved_errors: FAST_ARRAY[PARSE_ERROR]
  137. error_saved: BOOLEAN
  138. save_error (parse_error: PARSE_ERROR) is
  139. do
  140. saved_errors.add_last(parse_error)
  141. error_saved := True
  142. end
  143. print_saved_errors is
  144. do
  145. saved_errors.do_all(agent print_error)
  146. end
  147. feature {}
  148. print_error (a_error: PARSE_ERROR) is
  149. require
  150. a_error /= Void
  151. do
  152. std_error.put_line(a_error.message)
  153. end
  154. make (a_interpreter: like interpreter) is
  155. require
  156. a_interpreter /= Void
  157. do
  158. interpreter := a_interpreter
  159. create steps.make(a_interpreter)
  160. create debug_visitor.make(a_interpreter)
  161. create builder.make(a_interpreter)
  162. create saved_errors.with_capacity(2)
  163. ensure
  164. interpreter = a_interpreter
  165. end
  166. errors: LIBERTY_ERRORS
  167. debug_visitor: LIBERTY_INTERPRETER_DEBUGGER_VISITOR_IMPL
  168. interpreter: LIBERTY_INTERPRETER
  169. builder: LIBERTY_INTERPRETER_DEBUGGER_SEMANTICS_BUILDER
  170. debug_grammar: LIBERTY_INTERPRETER_DEBUGGER_GRAMMAR is
  171. once
  172. create Result.make(create {LIBERTY_INTERPRETER_DEBUGGER_FACTORY}.make)
  173. end
  174. parser_buffer: MINI_PARSER_BUFFER is
  175. once
  176. create Result
  177. end
  178. parser: DESCENDING_PARSER is
  179. once
  180. create Result.make
  181. end
  182. readline: READLINE_INPUT_STREAM is
  183. once
  184. create Result.make
  185. end
  186. invariant
  187. interpreter /= Void
  188. saved_errors /= Void
  189. end -- class LIBERTY_INTERPRETER_DEBUGGER