prolog-trace-viz 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/analyzer.d.ts +64 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +903 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/build-info.d.ts +15 -0
- package/dist/build-info.d.ts.map +1 -0
- package/dist/build-info.js +26 -0
- package/dist/build-info.js.map +1 -0
- package/dist/clauses.d.ts +15 -0
- package/dist/clauses.d.ts.map +1 -0
- package/dist/clauses.js +80 -0
- package/dist/clauses.js.map +1 -0
- package/dist/cli.d.ts +34 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +162 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +66 -0
- package/dist/errors.js.map +1 -0
- package/dist/executor.d.ts +25 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +115 -0
- package/dist/executor.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/mermaid.d.ts +47 -0
- package/dist/mermaid.d.ts.map +1 -0
- package/dist/mermaid.js +197 -0
- package/dist/mermaid.js.map +1 -0
- package/dist/output.d.ts +24 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +40 -0
- package/dist/output.js.map +1 -0
- package/dist/parser.d.ts +84 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +1007 -0
- package/dist/parser.js.map +1 -0
- package/dist/prolog-parser.d.ts +2 -0
- package/dist/prolog-parser.d.ts.map +1 -0
- package/dist/prolog-parser.js +2 -0
- package/dist/prolog-parser.js.map +1 -0
- package/dist/renderer.d.ts +33 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +131 -0
- package/dist/renderer.js.map +1 -0
- package/dist/wrapper.d.ts +30 -0
- package/dist/wrapper.d.ts.map +1 -0
- package/dist/wrapper.js +87 -0
- package/dist/wrapper.js.map +1 -0
- package/package.json +55 -0
- package/scripts/generate-build-info.js +63 -0
- package/scripts/release.js +151 -0
- package/tracer.pl +202 -0
package/tracer.pl
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
% Custom Prolog Tracer using prolog_trace_interception/4
|
|
2
|
+
% This tracer captures execution events and exports them as JSON
|
|
3
|
+
|
|
4
|
+
:- dynamic trace_event/1.
|
|
5
|
+
:- dynamic trace_active/0.
|
|
6
|
+
|
|
7
|
+
%% install_tracer/0
|
|
8
|
+
% Install the trace interception hook
|
|
9
|
+
install_tracer :-
|
|
10
|
+
asserta(trace_active),
|
|
11
|
+
trace.
|
|
12
|
+
|
|
13
|
+
%% remove_tracer/0
|
|
14
|
+
% Remove the trace interception hook and clean up
|
|
15
|
+
remove_tracer :-
|
|
16
|
+
notrace,
|
|
17
|
+
retractall(trace_active),
|
|
18
|
+
clear_trace.
|
|
19
|
+
|
|
20
|
+
%% clear_trace/0
|
|
21
|
+
% Clear all recorded trace events
|
|
22
|
+
clear_trace :-
|
|
23
|
+
retractall(trace_event(_)).
|
|
24
|
+
|
|
25
|
+
%% user:prolog_trace_interception(+Port, +Frame, +Choice, -Action)
|
|
26
|
+
% Hook predicate that intercepts trace events
|
|
27
|
+
user:prolog_trace_interception(Port, Frame, _Choice, continue) :-
|
|
28
|
+
trace_active,
|
|
29
|
+
!,
|
|
30
|
+
catch(
|
|
31
|
+
capture_trace_event(Port, Frame),
|
|
32
|
+
Error,
|
|
33
|
+
handle_trace_error(Error, Port, Frame)
|
|
34
|
+
).
|
|
35
|
+
user:prolog_trace_interception(_, _, _, continue).
|
|
36
|
+
|
|
37
|
+
%% handle_trace_error(+Error, +Port, +Frame)
|
|
38
|
+
% Handle errors during trace event capture
|
|
39
|
+
handle_trace_error(Error, Port, Frame) :-
|
|
40
|
+
catch(
|
|
41
|
+
(
|
|
42
|
+
prolog_frame_attribute(Frame, goal, Goal),
|
|
43
|
+
prolog_frame_attribute(Frame, level, Level),
|
|
44
|
+
assertz(trace_event(event(Port, Level, Goal, error(Error), no_clause, unknown)))
|
|
45
|
+
),
|
|
46
|
+
_,
|
|
47
|
+
assertz(trace_event(event(Port, 0, error_goal, error(Error), no_clause, unknown)))
|
|
48
|
+
).
|
|
49
|
+
|
|
50
|
+
%% capture_trace_event(+Port, +Frame)
|
|
51
|
+
% Capture a trace event with all relevant information
|
|
52
|
+
capture_trace_event(Port, Frame) :-
|
|
53
|
+
prolog_frame_attribute(Frame, goal, Goal),
|
|
54
|
+
prolog_frame_attribute(Frame, level, Level),
|
|
55
|
+
functor(Goal, Name, Arity),
|
|
56
|
+
format(atom(Predicate), '~w/~w', [Name, Arity]),
|
|
57
|
+
|
|
58
|
+
% Extract arguments for exit port
|
|
59
|
+
( Port = exit
|
|
60
|
+
-> extract_frame_arguments(Frame, Arity, Arguments)
|
|
61
|
+
; Arguments = []
|
|
62
|
+
),
|
|
63
|
+
|
|
64
|
+
% Extract clause information
|
|
65
|
+
extract_clause_info(Frame, Goal, ClauseInfo),
|
|
66
|
+
|
|
67
|
+
% Record the event
|
|
68
|
+
assertz(trace_event(event(Port, Level, Goal, Arguments, ClauseInfo, Predicate))).
|
|
69
|
+
|
|
70
|
+
%% extract_frame_arguments(+Frame, +Arity, -Arguments)
|
|
71
|
+
% Extract actual argument values from a frame
|
|
72
|
+
extract_frame_arguments(_, 0, []) :- !.
|
|
73
|
+
extract_frame_arguments(Frame, Arity, Arguments) :-
|
|
74
|
+
Arity > 0,
|
|
75
|
+
prolog_frame_attribute(Frame, goal, Goal),
|
|
76
|
+
Goal =.. [_|Args],
|
|
77
|
+
Arguments = Args.
|
|
78
|
+
|
|
79
|
+
%% extract_clause_info(+Frame, +Goal, -ClauseInfo)
|
|
80
|
+
% Extract clause information (head, body, line number) from a frame
|
|
81
|
+
extract_clause_info(Frame, Goal, clause(Head, Body, Line)) :-
|
|
82
|
+
catch(
|
|
83
|
+
(
|
|
84
|
+
prolog_frame_attribute(Frame, clause, ClauseRef),
|
|
85
|
+
ClauseRef \= 0,
|
|
86
|
+
clause(Head, Body, ClauseRef),
|
|
87
|
+
clause_property(ClauseRef, line_count(Line))
|
|
88
|
+
),
|
|
89
|
+
_,
|
|
90
|
+
fail
|
|
91
|
+
),
|
|
92
|
+
% Verify this clause matches the goal
|
|
93
|
+
subsumes_term(Head, Goal),
|
|
94
|
+
!.
|
|
95
|
+
extract_clause_info(_, _, no_clause).
|
|
96
|
+
|
|
97
|
+
%% export_trace_json(+File)
|
|
98
|
+
% Export all trace events as JSON
|
|
99
|
+
export_trace_json(File) :-
|
|
100
|
+
findall(Event, trace_event(Event), Events),
|
|
101
|
+
open(File, write, Stream),
|
|
102
|
+
write_json_events(Stream, Events),
|
|
103
|
+
close(Stream).
|
|
104
|
+
|
|
105
|
+
%% write_json_events(+Stream, +Events)
|
|
106
|
+
% Write events as JSON array
|
|
107
|
+
write_json_events(Stream, Events) :-
|
|
108
|
+
write(Stream, '[\n'),
|
|
109
|
+
write_events_list(Stream, Events),
|
|
110
|
+
write(Stream, '\n]').
|
|
111
|
+
|
|
112
|
+
%% write_events_list(+Stream, +Events)
|
|
113
|
+
% Write list of events with comma separation
|
|
114
|
+
write_events_list(_, []).
|
|
115
|
+
write_events_list(Stream, [Event]) :-
|
|
116
|
+
!,
|
|
117
|
+
write(Stream, ' '),
|
|
118
|
+
write_json_event(Stream, Event).
|
|
119
|
+
write_events_list(Stream, [Event|Rest]) :-
|
|
120
|
+
write(Stream, ' '),
|
|
121
|
+
write_json_event(Stream, Event),
|
|
122
|
+
write(Stream, ',\n'),
|
|
123
|
+
write_events_list(Stream, Rest).
|
|
124
|
+
|
|
125
|
+
%% write_json_event(+Stream, +Event)
|
|
126
|
+
% Write a single event as JSON object
|
|
127
|
+
write_json_event(Stream, event(Port, Level, Goal, Arguments, ClauseInfo, Predicate)) :-
|
|
128
|
+
format(Stream, '{', []),
|
|
129
|
+
format(Stream, '"port": "~w"', [Port]),
|
|
130
|
+
format(Stream, ', "level": ~w', [Level]),
|
|
131
|
+
format(Stream, ', "goal": ', []),
|
|
132
|
+
write_json_term(Stream, Goal),
|
|
133
|
+
format(Stream, ', "predicate": "~w"', [Predicate]),
|
|
134
|
+
|
|
135
|
+
% Write arguments if present (exit port)
|
|
136
|
+
( Arguments \= []
|
|
137
|
+
-> format(Stream, ', "arguments": ', []),
|
|
138
|
+
write_json_list(Stream, Arguments)
|
|
139
|
+
; true
|
|
140
|
+
),
|
|
141
|
+
|
|
142
|
+
% Write clause info if present
|
|
143
|
+
( ClauseInfo = clause(Head, Body, Line)
|
|
144
|
+
-> format(Stream, ', "clause": {', []),
|
|
145
|
+
format(Stream, '"head": ', []),
|
|
146
|
+
write_json_term(Stream, Head),
|
|
147
|
+
format(Stream, ', "body": ', []),
|
|
148
|
+
write_json_term(Stream, Body),
|
|
149
|
+
format(Stream, ', "line": ~w', [Line]),
|
|
150
|
+
format(Stream, '}', [])
|
|
151
|
+
; true
|
|
152
|
+
),
|
|
153
|
+
|
|
154
|
+
format(Stream, '}', []).
|
|
155
|
+
|
|
156
|
+
%% write_json_term(+Stream, +Term)
|
|
157
|
+
% Write a Prolog term as JSON string
|
|
158
|
+
write_json_term(Stream, Term) :-
|
|
159
|
+
format(atom(TermAtom), '~w', [Term]),
|
|
160
|
+
write_json_string(Stream, TermAtom).
|
|
161
|
+
|
|
162
|
+
%% write_json_string(+Stream, +Atom)
|
|
163
|
+
% Write an atom as JSON string with proper escaping
|
|
164
|
+
write_json_string(Stream, Atom) :-
|
|
165
|
+
atom_chars(Atom, Chars),
|
|
166
|
+
write(Stream, '"'),
|
|
167
|
+
write_escaped_chars(Stream, Chars),
|
|
168
|
+
write(Stream, '"').
|
|
169
|
+
|
|
170
|
+
%% write_escaped_chars(+Stream, +Chars)
|
|
171
|
+
% Write characters with JSON escaping
|
|
172
|
+
write_escaped_chars(_, []).
|
|
173
|
+
write_escaped_chars(Stream, [Char|Rest]) :-
|
|
174
|
+
( Char = '"'
|
|
175
|
+
-> write(Stream, '\\"')
|
|
176
|
+
; Char = '\\'
|
|
177
|
+
-> write(Stream, '\\\\')
|
|
178
|
+
; Char = '\n'
|
|
179
|
+
-> write(Stream, '\\n')
|
|
180
|
+
; Char = '\t'
|
|
181
|
+
-> write(Stream, '\\t')
|
|
182
|
+
; write(Stream, Char)
|
|
183
|
+
),
|
|
184
|
+
write_escaped_chars(Stream, Rest).
|
|
185
|
+
|
|
186
|
+
%% write_json_list(+Stream, +List)
|
|
187
|
+
% Write a list as JSON array
|
|
188
|
+
write_json_list(Stream, List) :-
|
|
189
|
+
write(Stream, '['),
|
|
190
|
+
write_json_list_items(Stream, List),
|
|
191
|
+
write(Stream, ']').
|
|
192
|
+
|
|
193
|
+
%% write_json_list_items(+Stream, +Items)
|
|
194
|
+
% Write list items with comma separation
|
|
195
|
+
write_json_list_items(_, []).
|
|
196
|
+
write_json_list_items(Stream, [Item]) :-
|
|
197
|
+
!,
|
|
198
|
+
write_json_term(Stream, Item).
|
|
199
|
+
write_json_list_items(Stream, [Item|Rest]) :-
|
|
200
|
+
write_json_term(Stream, Item),
|
|
201
|
+
write(Stream, ', '),
|
|
202
|
+
write_json_list_items(Stream, Rest).
|