val writeln_message = output_message Markup.writelnN; val warning_message = output_message Markup.warningN; val error_message = output_message Markup.errorN;
fun error_wrapper e =
(case Exn.result e () of
Exn.Res res => res
| Exn.Exn exn => error_message (Runtime.exn_message exn));
(* thread input *)
val thread_input =
Synchronized.var "Debugger.state" (NONE: stringlist Queue.T Symtab.table option);
fun init_input () = Synchronized.change thread_input (K (SOME Symtab.empty)); fun exit_input () = Synchronized.change thread_input (K NONE);
fun input thread_name msg = if null msg then error "Empty input" else
Synchronized.change thread_input
(Option.map (Symtab.map_default (thread_name, Queue.empty) (Queue.enqueue msg)));
fun get_input thread_name =
Synchronized.guarded_access thread_input
(fn NONE => SOME ([], NONE)
| SOME input =>
(case Symtab.lookup input thread_name of
NONE => NONE
| SOME queue => let val (msg, queue') = Queue.dequeue queue; val input' = if Queue.is_empty queue' then Symtab.delete_safe thread_name input else Symtab.update (thread_name, queue') input; in SOME (msg, SOME input') end));
(* global break *)
local val break = Synchronized.var "Debugger.break"false; in
fun is_break () = Synchronized.value break; fun set_break b = Synchronized.change break (K b);
end;
(** thread state **)
(* stack frame during debugging *)
val debugging_var = Thread_Data.var () : PolyML.DebuggerInterface.debugState list Thread_Data.var;
fun get_debugging () = the_default [] (Thread_Data.get debugging_var); val is_debugging = not o null o get_debugging;
fun with_debugging e =
Thread_Data.setmp debugging_var
(SOME (PolyML.DebuggerInterface.debugState (Thread.Thread.self ()))) e ();
fun the_debug_state thread_name index =
(case get_debugging () of
[] => error ("Missing debugger information for thread " ^ quote thread_name)
| states => if index < 0 orelse index >= length states then
error ("Bad debugger stack index " ^ signed_string_of_int index ^ " for thread " ^
quote thread_name) else nth states index);
fun environment SML = if SML then ML_Env.SML else ML_Env.Isabelle; fun operations SML = if SML then ML_Env.SML_operations else ML_Env.Isabelle_operations;
fun eval_setup thread_name index SML context =
context
|> Context_Position.set_visible_generic false
|> ML_Env.add_name_space (environment SML)
(PolyML.DebuggerInterface.debugNameSpace (the_debug_state thread_name index));
fun eval_context thread_name index SML toks = let val context = Context.the_generic_context (); val context1 = if SML orelse forall (fn Antiquote.Text tok => ML_Lex.is_improper tok | _ => false) toks then context else let val context' = context
|> eval_setup thread_name index SML
|> ML_Context.exec (fn () =>
evaluate {SML = SML, verbose = true} (ML_Lex.read "val ML_context = " @ toks)); fun try_exec toks = try (ML_Context.exec (fn () => evaluate {SML = false, verbose = false} toks)) context'; in
(case get_first try_exec context_attempts of
SOME context2 => context2
| NONE => error "Malformed context: expected type theory, Proof.context, Context.generic") end; in context1 |> eval_setup thread_name index SML end;
in
fun eval thread_name index SML txt1 txt2 = let val (toks1, toks2) = apply2 (#read_source (operations SML) o Input.string) (txt1, txt2); val context = eval_context thread_name index SML toks1; in Context.setmp_generic_context (SOME context) (evaluate {SML = SML, verbose = true}) toks2 end;
fun print_vals thread_name index SML txt = let val toks = #read_source (operations SML) (Input.string txt) val context = eval_context thread_name index SML toks; val space = PolyML.DebuggerInterface.debugNameSpace (the_debug_state thread_name index);
funprint x =
Pretty.from_ML
(PolyML.NameSpace.Values.printWithType
(x, FixedInt.fromInt (ML_Print_Depth.get_print_depth ()), SOME space)); fun print_all () =
#allVal (PolyML.DebuggerInterface.debugLocalNameSpace (the_debug_state thread_name index)) ()
|> sort_by #1 |> map (Pretty.item o single o print o #2)
|> Pretty.chunks |> Pretty.string_of |> writeln_message; in Context.setmp_generic_context (SOME context) print_all () end;
fun debugger_loop thread_name =
Thread_Attributes.uninterruptible_body (fn run => let fun loop () =
(debugger_state thread_name; if debugger_command thread_name then loop () else ()); val result = Exn.capture (run with_debugging) loop; val _ = debugger_state thread_name; in Exn.release result end);
end;
(** protocol commands **)
val _ =
Protocol_Command.define "Debugger.init"
(fn [] =>
(init_input ();
PolyML.DebuggerInterface.setOnBreakPoint
(SOME (fn (_, break) => ifnot (is_debugging ()) andalso (! break orelse is_break () orelse is_stepping ()) then
(casetry (Isabelle_Thread.print o Isabelle_Thread.self) () of
SOME thread_name => debugger_loop thread_name
| NONE => ()) else ()))));
val _ =
Protocol_Command.define "Debugger.breakpoint"
(fn [node_name, id0, breakpoint0, breakpoint_state0] => let val id = Value.parse_int id0; val breakpoint = Value.parse_int breakpoint0; val breakpoint_state = Value.parse_bool breakpoint_state0;
fun err () = error ("Bad exec for command " ^ Value.print_int id); in
(case Document.command_exec (Document.state ()) node_name id of
SOME (eval, _) => if Command.eval_finished eval then let val st = Command.eval_result_state eval; val ctxt = Toplevel.presentation_context st; in
(case ML_Env.get_breakpoint (Context.Proof ctxt) breakpoint of
SOME (b, _) => b := breakpoint_state
| NONE => err ()) end else err ()
| NONE => err ()) end);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.1Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.