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=[])).
 session_start(+ServerSpec, -Session) is det
Start a new DAP session with server ServerSpec and unify Session with the newly created session's state.

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).
 session_stop(+Session) is det
Stop the DAP session Session and the associated DAP server process.
   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)