Skip to content

Commit 3b900e5

Browse files
committed
ADD: Support evaluate request
1 parent 179b1e6 commit 3b900e5

File tree

6 files changed

+94
-28
lines changed

6 files changed

+94
-28
lines changed

pack.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name(debug_adapter).
22
title('Debug Adapter Protocol package for SWI-Prolog').
3-
version('0.4.0').
3+
version('0.4.1').
44
author('Eshel Yaron', '[email protected]').
55
maintainer('Eshel Yaron', '[email protected]').
66
packager('Eshel Yaron', '[email protected]').
77
home('https://github.com/eshelyaron/debug_adapter').
8-
download('https://github.com/eshelyaron/debug_adapter/releases/download/v0.4.0/debug_adapter-0.4.0.zip').
8+
download('https://github.com/eshelyaron/debug_adapter/releases/download/v0.4.1/debug_adapter-0.4.1.zip').

prolog/TODO

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
* TODO `disconnect` handling is a bit hacky, should be revised
2-
* TODO `stopped` events should report a `reason` that conforms to the DAP specs.
3-
Currently (v0.2.1) we report the name of the *port* as the `reason`, because `dap-mode` only
4-
displays the `reason` field by default. This is especially important if the `reason` should be
5-
`expection`, in which case [[file:~/checkouts/dap-mode/dap-mode.el::when (string= "exception" reason][`dap-mode` has a special case for retrieving further info]].
61
* TODO Emit `output` events when applicable
7-
* TODO Support breakpoints
82
* TODO Utilize the DAP Json Schema
93
DAP is defined by machine-reabable Json Schema draft 4, we should utilize it to eliminate manual
10-
implementation of many procotol details.
4+
implementation of many protocol details.
115
* TODO Use `predicate_options/1` for documentation and safety where warranted
126
* TODO Consider using [[https://www.swi-prolog.org/pldoc/doc_for?object=message_hook/3][`message_link/3`]] to implement the DAP `output` event
137
* TODO Consider the security of the debugger

prolog/debug_adapter/frame.pl

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
da_frame_parent/2,
77
da_frame_clause/2,
88
da_frame_predicate_indicator/2,
9-
da_frame_alternative/3,
9+
da_alternative/2,
1010
da_frame_alternative_frame/2,
1111
da_frame_parent_pc/2,
1212
da_frame_pc_stack/4,
1313
da_frame_pc_source_span/3,
1414
da_frame_clause_source_span/2,
1515
da_frame_port_source_span/3,
1616
da_frame_scopes/4,
17+
da_frame_evaluate/4,
1718
da_referenced_variables/2
1819
]
1920
).
@@ -137,27 +138,39 @@
137138
prolog_frame_attribute(FrameId, predicate_indicator, PredicateIndicator).
138139

139140

140-
%! da_frame_alternative(+FrameId, +ChoicePoint, -Alternative) is det.
141+
%! da_alternative(+ChoicePoint, -Alternative) is det.
141142
%
142143
% Alternative is unified with a term describing the location from which execution will be
143-
% resumed in case the current goal of FrameId fails, which is one of the following:
144+
% resumed in case the current goal fails, which is one of the following:
144145
% - frame(AlternativeFrameId)
145-
% If frame FrameId has an _alternative frame_, where AlternativeFrameId is the IDf of the
146-
% frame from which execution will resume in case the goal associated with frame FrameId fails,
146+
% If ChoicePoint refers to an _alternative frame_, where AlternativeFrameId is the ID of the
147+
% frame from which execution will resume in case the goal associated with the current frame fails,
147148
% - jump(PC)
148-
% If frame FrameId has as in-clause choice point, where PC is the program counter in the frame
149+
% If ChoicePoint is an in-clause choice point, where PC is the program counter in the frame
149150
% from which execution will resume is case the current goal fails or
151+
% - clause(Clause)
152+
% If ChoicePoint refers to an alternative clause Clause
150153
% - null
151-
% If the goal associated with frame FrameId has no alternative, i.e. it must succeed for
152-
% the frame to succeed
154+
% If ChoicePoint is `none`
153155

154-
:- det(da_frame_alternative/3).
155-
da_frame_alternative(_FrameId, ChoicePoint, jump(PC)) :-
156-
prolog_choice_attribute(ChoicePoint, type, jump),
156+
:- det(da_alternative/2).
157+
da_alternative(ChoicePoint, Alternative) :-
158+
prolog_choice_attribute(ChoicePoint, type, Type),
159+
da_alternative(Type, ChoicePoint, Alternative).
160+
161+
:- det(da_alternative/3).
162+
da_alternative(jump, ChoicePoint, jump(PC)) :-
157163
!,
158164
prolog_choice_attribute(ChoicePoint, pc, PC).
159-
da_frame_alternative(FrameId, _ChoicePoint, frame(AlternativeFrameId)) :-
160-
da_frame_alternative_frame(FrameId, AlternativeFrameId).
165+
da_alternative(clause, ChoicePoint, clause(Clause)) :-
166+
!,
167+
prolog_choice_attribute(ChoicePoint, clause, Clause).
168+
da_alternative(none, _, null) :- !.
169+
da_alternative(debug, _, null) :- !.
170+
da_alternative(top, _, null) :- !.
171+
da_alternative(_, ChoicePoint, frame(Frame)) :-
172+
!,
173+
prolog_choice_attribute(ChoicePoint, frame, Frame).
161174

162175

163176
%! da_frame_alternative_frame(+FrameId, -AlternativeFrameId) is det.
@@ -166,7 +179,7 @@
166179
% with the atom `null` if FrameId does not have an alternative frame.
167180

168181
:- det(da_frame_alternative_frame/2).
169-
da_frame_alternative_frame(FrameId, AlternativeFrameId) :-
182+
da_frame_alternative_frame(FrameId, frame(AlternativeFrameId)) :-
170183
prolog_frame_attribute(FrameId, alternative, AlternativeFrameId),
171184
!.
172185
da_frame_alternative_frame(_, null).
@@ -388,3 +401,34 @@
388401
da_frame_locals(Frame, NI, VarNames, T)
389402
; Variables = []
390403
).
404+
405+
406+
:- det(da_frame_evaluate/4).
407+
da_frame_evaluate(FrameId, SourceTerm, Result, Bindings) :-
408+
read_term_from_atom(SourceTerm, Goal, [variable_names(Bindings)]),
409+
da_frame_clause(FrameId, ClauseRef),
410+
da_clause_variable_names(ClauseRef, ClauseVarNames),
411+
da_frame_unify_variables(FrameId, ClauseVarNames, Bindings),
412+
da_evaluate(Goal, Result).
413+
414+
415+
:- det(da_evaluate/2).
416+
da_evaluate(Goal, Result) :-
417+
catch(Goal, Result, true),
418+
!,
419+
( var(Result)
420+
-> Result = true
421+
; true
422+
).
423+
da_evaluate(_, false).
424+
425+
426+
:- det(da_frame_unify_variables/3).
427+
da_frame_unify_variables(_FrameId, _ClauseVarNames, [ ]) :- !.
428+
da_frame_unify_variables( FrameId, ClauseVarNames, [VarName=Value|T]) :- !,
429+
( arg(I, ClauseVarNames, VarName)
430+
-> prolog_frame_attribute(FrameId, argument(I), Value),
431+
da_frame_unify_variables(FrameId, ClauseVarNames, T)
432+
; true
433+
),
434+
da_frame_unify_variables(FrameId, ClauseVarNames, T).

prolog/debug_adapter/server.pl

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,11 @@
117117
Seq = Seq0
118118
).
119119

120+
:- det(da_server_handled_debugee_message/7).
120121
da_server_handled_debugee_message(_DebugeeThreadId,
121122
loaded_source(Reason, SourcePath),
122123
Out, State, State, Seq0, Seq) :-
124+
!,
123125
file_base_name(SourcePath, BaseName),
124126
dap_event(Out, Seq0, "loadedSource", _{ reason : Reason,
125127
source : _{ name : BaseName,
@@ -131,6 +133,7 @@
131133
da_server_handled_debugee_message(DebugeeThreadId,
132134
stopped(Reason, Description, Text, BreakpointIds),
133135
Out, State, State, Seq0, Seq) :-
136+
!,
134137
dap_event(Out, Seq0, "stopped", _{ threadId : DebugeeThreadId,
135138
reason : Reason,
136139
description : Description,
@@ -142,35 +145,47 @@
142145
da_server_handled_debugee_message(_DebugeeThreadId,
143146
stack_trace(RequestSeq, StackFrames0),
144147
Out, State, State, Seq0, Seq) :-
148+
!,
145149
maplist(prolog_dap_stack_frame, StackFrames0, StackFrames),
146150
dap_response(Out, Seq0, RequestSeq, "stackTrace", _{stackFrames:StackFrames}),
147151
succ(Seq0, Seq).
148152
da_server_handled_debugee_message(_DebugeeThreadId,
149153
exception_info(RequestSeq, ExceptionTerm),
150154
Out, State, State, Seq0, Seq) :-
155+
!,
151156
prolog_dap_exception(ExceptionTerm, ExceptionId),
152157
dap_response(Out, Seq0, RequestSeq, "exceptionInfo", _{exceptionId:ExceptionId, description:ExceptionId}),
153158
succ(Seq0, Seq).
154159
da_server_handled_debugee_message(_DebugeeThreadId,
155160
scopes(RequestSeq, Scopes0),
156161
Out, State, State, Seq0, Seq) :-
162+
!,
157163
maplist(prolog_dap_scope, Scopes0, Scopes),
158164
dap_response(Out, Seq0, RequestSeq, "scopes", _{scopes:Scopes}),
159165
succ(Seq0, Seq).
160166
da_server_handled_debugee_message(_DebugeeThreadId,
161167
variables(RequestSeq, Variables0),
162168
Out, State, State, Seq0, Seq) :-
169+
!,
163170
maplist(prolog_dap_variable, Variables0, Variables),
164171
dap_response(Out, Seq0, RequestSeq, "variables", _{variables:Variables}),
165172
succ(Seq0, Seq).
173+
da_server_handled_debugee_message(_DebugeeThreadId,
174+
evaluate(RequestSeq, Result, Bindings),
175+
Out, State, State, Seq0, Seq) :-
176+
!,
177+
format(string(Res), "~w~n~w.", [Bindings, Result]),
178+
dap_response(Out, Seq0, RequestSeq, "evaluate", _{result:Res, variablesReference:0}),
179+
succ(Seq0, Seq).
166180
da_server_handled_debugee_message(_DebugeeThreadId,
167181
exited(_ExitCode),
168-
_Out, State, State, Seq, Seq).
182+
_Out, State, State, Seq, Seq) :- !.
169183
% dap_event(Out, Seq0, "exited", _{exitCode:ExitCode}),
170184
% succ(Seq0, Seq).
171185
da_server_handled_debugee_message(DebugeeThreadId,
172186
thread_exited,
173187
Out, State0, State, Seq0, Seq) :-
188+
!,
174189
dap_event(Out, Seq0, "thread", _{ reason : "exited",
175190
threadId : DebugeeThreadId
176191
}),
@@ -337,6 +352,14 @@
337352
_{ arguments:Args } :< Message,
338353
_{ variablesReference:VariablesRef } :< Args,
339354
maplist({RequestSeq, VariablesRef}/[debugee(PrologThreadId, _, _)]>>thread_send_message(PrologThreadId, variables(RequestSeq, VariablesRef)), State).
355+
da_server_command("evaluate", RequestSeq, Message, _Out, _W, State, State, Seq, Seq) :-
356+
_{ arguments : Args } :< Message,
357+
_{ expression : SourceTerm,
358+
frameId : FrameId,
359+
context : Context
360+
} :< Args,
361+
debug(dap(tracer), "handling evaluate request arguments with ~w ~w ~w", [FrameId, SourceTerm, Context]),
362+
maplist({RequestSeq, FrameId, SourceTerm}/[debugee(PrologThreadId, _, _)]>>thread_send_message(PrologThreadId, evaluate(RequestSeq, FrameId, SourceTerm)), State).
340363
da_server_command("setBreakpoints", RequestSeq, Message, Out, _W, State, State, Seq0, Seq) :-
341364
_{ arguments : Args } :< Message,
342365
_{ source : DAPSource,
@@ -394,7 +417,8 @@
394417

395418
da_server_capabilities(_{ supportsConfigurationDoneRequest : true,
396419
supportsExceptionInfoRequest : true,
397-
supportsRestartFrame : true
420+
supportsRestartFrame : true,
421+
supportsEvaluateForHovers : true
398422
}
399423
).
400424

prolog/debug_adapter/stack.pl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@
3737
da_frame_pc_stack(ParentFrameId, PC, da_stack_frame_info, StackTrace).
3838

3939
da_stack_frame_info(FrameId, PC,
40-
stack_frame(FrameId, pc(PC), PredicateIndicator, label(frame, AlternativeFrameId), SourceSpan)) :-
40+
stack_frame(FrameId, pc(PC), PredicateIndicator, Alternative, SourceSpan)) :-
4141
da_frame_predicate_indicator(FrameId, PredicateIndicator),
42-
da_frame_alternative_frame(FrameId, AlternativeFrameId),
42+
da_frame_alternative_frame(FrameId, Alternative),
4343
da_frame_pc_source_span(FrameId, PC, SourceSpan).
4444

4545
da_stack_frame_at_port(FrameId, Port, ChoicePoint,
4646
stack_frame(FrameId, port(Port), PredicateIndicator, Alternative, SourceSpan)) :-
4747
da_frame_predicate_indicator(FrameId, PredicateIndicator),
48-
da_frame_alternative(FrameId, ChoicePoint, Alternative),
48+
da_alternative(ChoicePoint, Alternative),
4949
da_frame_port_source_span(FrameId, Port, SourceSpan).

prolog/debug_adapter/tracer.pl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@
161161
atom_string(Atom, Reason).
162162

163163
:- det(da_tracer_handled_message/7).
164+
da_tracer_handled_message(evaluate(RequestId, FrameId, SourceTerm), _Port, _Frame, _Choice, loop, S, W) :-
165+
!,
166+
da_frame_evaluate(FrameId, SourceTerm, Result, Bindings),
167+
da_debugee_emitted_message(evaluate(RequestId, Result, Bindings), S, W).
164168
da_tracer_handled_message(stack_trace(RequestId), Port, Frame, Choice, loop, S, W) :-
165169
!,
166170
da_stack_frame_at_port(Frame, Port, Choice, ActiveFrame),

0 commit comments

Comments
 (0)