1:- module( 2 da_session, 3 [ 4 session_request/5, % session_request(+Type, +Request, -RequestSeq, +Session0, -Session) 5 session_request_response/5, % session_request_response(+Type, +Request, -Response, +Session0, -Session) 6 session_response/5, % session_response(+Type, +RequestSeq, -Response, +Session0, -Session) 7 session_event/4, % session_event(+Type, -Event, +Session0, -Session) 8 session_reverse_request/4, % session_reverse_request(+Type, -Request, +Session0, -Session) 9 session_start/2, % session_start(+ServerSpec, -Session) 10 session_stop/1 % session_stop(+Session) 11 ] 12 ). 13 14:- use_module(protocol). 15 16:- record(session(in, out, pid, seq=1, seen=[])).
ServerSpec is a non empty list with head Exec and tail Args, where Exec specifies the DAP server executable and Args is a list of command line arguments passed to the server's invocation.
26session_start([Exec|Args], Session) :-
27 process_create(Exec, Args,
28 [ stdin(pipe(O)),
29 stdout(pipe(I)),
30 process(P)
31 ]),
32 set_stream(I, buffer(full)),
33 set_stream(I, newline(dos)),
34 set_stream(O, buffer(false)),
35 make_session([in(I), out(O), pid(P)], Session).
41session_stop(Session) :- 42 session_in(Session, I), 43 session_out(Session, O), 44 session_pid(Session, P), 45 close(O), 46 close(I), 47 process_wait(P, Status, [timeout(0)]), 48 ( Status == timeout 49 -> process_kill(P) 50 ; true 51 ). 52 53session_request(Type, Request, Seq0, Session0, Session) :- 54 session_out(Session0, Out), 55 session_seq(Session0, Seq0), 56 dap_request(Out, Seq0, Type, Request), 57 Seq is Seq0 + 1, 58 set_seq_of_session(Seq, Session0, Session). 59 60session_request_response(Type, Request, Response, Session0, Session) :- 61 session_request(Type, Request, ReqSeq, Session0, Session1), 62 session_response(Type, ReqSeq, Response, Session1, Session). 63 64session_response(Type0, ReqSeq, Result, Session, Session) :- 65 atom_string(Type0, Type), 66 session_already(Session, response(_ReqSeq, ReqSeq, Type, Success, Message, Response)), 67 !, 68 session_response_result(Success, Message, Response, Result). 69session_response(Type, ReqSeq, Result, Session0, Session) :- 70 session_next(Session0, Session1), 71 session_response(Type, ReqSeq, Result, Session1, Session). 72 73session_event(Type0, Result, Session, Session) :- 74 atom_string(Type0, Type), 75 session_already(Session, event(_Seq, Type, Result)). 76session_event(Type, Result, Session0, Session) :- 77 session_next(Session0, Session1), 78 session_event(Type, Result, Session1, Session). 79 80session_reverse_request(Type0, Result, Session, Session) :- 81 atom_string(Type0, Type), 82 session_already(Session, request(_Seq, Type, Result)). 83session_reverse_request(Type, Result, Session0, Session) :- 84 session_next(Session0, Session1), 85 session_reverse_request(Type, Result, Session1, Session). 86 87session_next(Session0, Session) :- 88 session_in(Session0, I), 89 dap_read(I, R), 90 _{ type : Type0 } :< R, 91 debug(dap(session), "Received message ~w : ~w", [Type0, R]), 92 atom_string(Type, Type0), 93 session_see(Type, R, Session0, Session). 94 95session_see(response, R, Session0, Session) :- 96 _{ seq: Seq, request_seq : ReqSeq, command : Command, success : Success } :< R, 97 ( get_dict(message, R, Message) 98 -> true 99 ; Message = null 100 ), 101 ( get_dict(body, R, Body) 102 -> true 103 ; Body = null 104 ), 105 session_seen(Session0, Seen0), 106 set_seen_of_session([response(Seq, ReqSeq, Command, Success, Message, Body)|Seen0], Session0, Session). 107session_see(event, E, Session0, Session) :- 108 _{ seq : Seq, event : Event } :< E, 109 ( get_dict(body, E, Body) 110 -> true 111 ; Body = null 112 ), 113 session_seen(Session0, Seen0), 114 set_seen_of_session([event(Seq, Event, Body)|Seen0], Session0, Session). 115session_see(request, R, Session0, Session) :- 116 _{ seq : Seq, command : Command } :< R, 117 ( get_dict(arguments, R, Args) 118 -> true 119 ; Args = null 120 ), 121 session_seen(Session0, Seen0), 122 set_seen_of_session([request(Seq, Command, Args)|Seen0], Session0, Session). 123 124session_response_result(true , _, Result, true:Result). 125session_response_result(false, Result, _, false:Result). 126session_response_result(null, Result, _, false:Result). 127 128session_already(Session, Eventuality) :- 129 session_seen(Session, Seen), 130 memberchk(Eventuality, Seen)