YAP 7.1.0
block_diagram.yap
Go to the documentation of this file.
1%%% -*- Mode: Prolog; -*-
2
3/**
4 * @file block_diagram.yap
5 * @author Theofrastos Mantadelis, Sugestions from Paulo Moura
6 * @date Tue Nov 17 14:12:02 2015
7 *
8 * @brief Graph the program structure.
9 *
10 * @{
11*/
12
13%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14%
15% Flags was developed at Katholieke Universiteit Leuven
16%
17% Copyright 2010
18% Katholieke Universiteit Leuven
19%
20% Contributions to this file:
21% Author: Theofrastos Mantadelis
22% Sugestions: Paulo Moura
23% Version: 1
24% Date: 19/11/2010
25%
26%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27%
28% Artistic License 2.0
29%
30% Copyright (c) 2000-2006, The Perl Foundation.
31%
32% Everyone is permitted to copy and distribute verbatim copies of this
33% license document, but changing it is not allowed. Preamble
34%
35% This license establishes the terms under which a given free software
36% Package may be copied, modified, distributed, and/or
37% redistributed. The intent is that the Copyright Holder maintains some
38% artistic control over the development of that Package while still
39% keeping the Package available as open source and free software.
40%
41% You are always permitted to make arrangements wholly outside of this
42% license directly with the Copyright Holder of a given Package. If the
43% terms of this license do not permit the full use that you propose to
44% make of the Package, you should contact the Copyright Holder and seek
45% a different licensing arrangement. Definitions
46%
47% "Copyright Holder" means the individual(s) or organization(s) named in
48% the copyright notice for the entire Package.
49%
50% "Contributor" means any party that has contributed code or other
51% material to the Package, in accordance with the Copyright Holder's
52% procedures.
53%
54% "You" and "your" means any person who would like to copy, distribute,
55% or modify the Package.
56%
57% "Package" means the collection of files distributed by the Copyright
58% Holder, and derivatives of that collection and/or of those files. A
59% given Package may consist of either the Standard Version, or a
60% Modified Version.
61%
62% "Distribute" means providing a copy of the Package or making it
63% accessible to anyone else, or in the case of a company or
64% organization, to others outside of your company or organization.
65%
66% "Distributor Fee" means any fee that you charge for Distributing this
67% Package or providing support for this Package to another party. It
68% does not mean licensing fees.
69%
70% "Standard Version" refers to the Package if it has not been modified,
71% or has been modified only in ways explicitly requested by the
72% Copyright Holder.
73%
74% "Modified Version" means the Package, if it has been changed, and such
75% changes were not explicitly requested by the Copyright Holder.
76%
77% "Original License" means this Artistic License as Distributed with the
78% Standard Version of the Package, in its current version or as it may
79% be modified by The Perl Foundation in the future.
80%
81% "Source" form means the source code, documentation source, and
82% configuration files for the Package.
83%
84% "Compiled" form means the compiled bytecode, object code, binary, or
85% any other form resulting from mechanical transformation or translation
86% of the Source form.
87%
88%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89%
90% Permission for Use and Modification Without Distribution
91%
92% (1) You are permitted to use the Standard Version and create and use
93% Modified Versions for any purpose without restriction, provided that
94% you do not Distribute the Modified Version.
95%
96% Permissions for Redistribution of the Standard Version
97%
98% (2) You may Distribute verbatim copies of the Source form of the
99% Standard Version of this Package in any medium without restriction,
100% either gratis or for a Distributor Fee, provided that you duplicate
101% all of the original copyright notices and associated disclaimers. At
102% your discretion, such verbatim copies may or may not include a
103% Compiled form of the Package.
104%
105% (3) You may apply any bug fixes, portability changes, and other
106% modifications made available from the Copyright Holder. The resulting
107% Package will still be considered the Standard Version, and as such
108% will be subject to the Original License.
109%
110% Distribution of Modified Versions of the Package as Source
111%
112% (4) You may Distribute your Modified Version as Source (either gratis
113% or for a Distributor Fee, and with or without a Compiled form of the
114% Modified Version) provided that you clearly document how it differs
115% from the Standard Version, including, but not limited to, documenting
116% any non-standard features, executables, or modules, and provided that
117% you do at least ONE of the following:
118%
119% (a) make the Modified Version available to the Copyright Holder of the
120% Standard Version, under the Original License, so that the Copyright
121% Holder may include your modifications in the Standard Version. (b)
122% ensure that installation of your Modified Version does not prevent the
123% user installing or running the Standard Version. In addition, the
124% modified Version must bear a name that is different from the name of
125% the Standard Version. (c) allow anyone who receives a copy of the
126% Modified Version to make the Source form of the Modified Version
127% available to others under (i) the Original License or (ii) a license
128% that permits the licensee to freely copy, modify and redistribute the
129% Modified Version using the same licensing terms that apply to the copy
130% that the licensee received, and requires that the Source form of the
131% Modified Version, and of any works derived from it, be made freely
132% available in that license fees are prohibited but Distributor Fees are
133% allowed.
134%
135% Distribution of Compiled Forms of the Standard Version or
136% Modified Versions without the Source
137%
138% (5) You may Distribute Compiled forms of the Standard Version without
139% the Source, provided that you include complete instructions on how to
140% get the Source of the Standard Version. Such instructions must be
141% valid at the time of your distribution. If these instructions, at any
142% time while you are carrying out such distribution, become invalid, you
143% must provide new instructions on demand or cease further
144% distribution. If you provide valid instructions or cease distribution
145% within thirty days after you become aware that the instructions are
146% invalid, then you do not forfeit any of your rights under this
147% license.
148%
149% (6) You may Distribute a Modified Version in Compiled form without the
150% Source, provided that you comply with Section 4 with respect to the
151% Source of the Modified Version.
152%
153% Aggregating or Linking the Package
154%
155% (7) You may aggregate the Package (either the Standard Version or
156% Modified Version) with other packages and Distribute the resulting
157% aggregation provided that you do not charge a licensing fee for the
158% Package. Distributor Fees are permitted, and licensing fees for other
159% components in the aggregation are permitted. The terms of this license
160% apply to the use and Distribution of the Standard or Modified Versions
161% as included in the aggregation.
162%
163% (8) You are permitted to link Modified and Standard Versions with
164% other works, to embed the Package in a larger work of your own, or to
165% build stand-alone binary or bytecode versions of applications that
166% include the Package, and Distribute the result without restriction,
167% provided the result does not expose a direct interface to the Package.
168%
169% Items That are Not Considered Part of a Modified Version
170%
171% (9) Works (including, but not limited to, modules and scripts) that
172% merely extend or make use of the Package, do not, by themselves, cause
173% the Package to be a Modified Version. In addition, such works are not
174% considered parts of the Package itself, and are not subject to the
175% terms of this license.
176%
177% General Provisions
178%
179% (10) Any use, modification, and distribution of the Standard or
180% Modified Versions is governed by this Artistic License. By using,
181% modifying or distributing the Package, you accept this license. Do not
182% use, modify, or distribute the Package, if you do not accept this
183% license.
184%
185% (11) If your Modified Version has been derived from a Modified Version
186% made by someone other than you, you are nevertheless required to
187% ensure that your Modified Version complies with the requirements of
188% this license.
189%
190% (12) This license does not grant you the right to use any trademark,
191% service mark, tradename, or logo of the Copyright Holder.
192%
193% (13) This license includes the non-exclusive, worldwide,
194% free-of-charge patent license to make, have made, use, offer to sell,
195% sell, import and otherwise transfer the Package with respect to any
196% patent claims licensable by the Copyright Holder that are necessarily
197% infringed by the Package. If you institute patent litigation
198% (including a cross-claim or counterclaim) against any party alleging
199% that the Package constitutes direct or contributory patent
200% infringement, then this Artistic License to you shall terminate on the
201% date that such litigation is filed.
202%
203% (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
204% HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
205% WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
206% PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
207% PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
208% HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
209% INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
210% OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
211%
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213
214/** @defgroup block_diagram Block Diagram
215@ingroup YAPLibrary
216@{
217
218This library provides a way of visualizing a prolog program using
219modules with blocks. To use it use:
220`:-use_module(library(block_diagram))`.
221
222
223*/
224
225:- module(block_diagram, [make_diagram/2, make_diagram/5]).
226
227/* ---------------------------------------------------------------------- *\
228|* Missing stuff: a parameter that bounds the module connection depth *|
229|* and a parameter that diseables/limits the text over edges *|
230\* ---------------------------------------------------------------------- */
231
232:- style_check(all).
233:- yap_flag(unknown, error).
234
235
236:- term_to_atom/2use_module(library(charsio), []).
237:- memberchk/2member/2append/3use_module(library(lists), [, , ]).
238:- working_directory/2use_module(library(system), []).
239:- seen_module/1parameter/1dynamic([, ]).
240
241parameter(texts((+inf))).
242parameter(depth((+inf))).
243parameter(default_ext('.yap')).
244
245/** @pred make_diagram(+Inputfilename, +Ouputfilename)
246
247
248
249This will crawl the files following the use_module, ensure_loaded directives withing the inputfilename.
250The result will be a file in dot format.
251You can make a pdf at the shell by asking `dot -Tpdf filename > output.pdf`.
252
253
254*/
255make_diagram(InputFile, OutputFile):-
256 tell(OutputFile),
257 write('digraph G {\nrankdir=BT'), write,
258 extract_name_file(InputFile, Name, File),
259 nb_setval(depth, 0),
260 read_module_file(File, Name),
261 read_module_file,
262 write('}'), write,
263 write.
264
265/** @pred make_diagram(+Inputfilename, +Ouputfilename, +Predicate, +Depth, +Extension)
266
267
268The same as make_diagram/2 but you can define how many of the imported/exporeted predicates will be shown with predicate, and how deep the crawler is allowed to go with depth. The extension is used if the file use module directives do not include a file extension.
269
270*/
271make_diagram(InputFile, OutputFile, Texts, Depth, Ext):-
272 integer(Texts),
273 integer(Depth),
274 retractall(parameter(_)),
275 assertz(parameter(texts(Texts))),
276 assertz(parameter(depth(Depth))),
277 assertz(parameter(default_ext(Ext))),
278 make_diagram(InputFile, OutputFile),
279 retractall(parameter(_)),
280 assertz(parameter(texts((+inf)))),
281 assertz(parameter(depth((+inf)))),
282 assertz(parameter(default_ext('.yap'))).
283
284path_seperator('\\'):-
285 yap_flag(windows, true), yap_flag.
286path_seperator('/').
287
288split_path_file(PathFile, Path, File):-
289 path_seperator(PathSeperator),
290 atom_concat(Path, File, PathFile),
291 name(PathSeperator, [PathSeperatorName]),
292 name(File, FileName),
293 \+ memberchk(PathSeperatorName, FileName),
294 memberchk.
295split_file_ext(FileExt, File, Ext):-
296 atom_concat(File, Ext, FileExt),
297 atom_concat('.', _, Ext),
298 name('.', [DotName]),
299 name(Ext, ExtName),
300 findall(A, (member(A, ExtName), A = DotName), L),
301 length(L, 1), length.
302
303
304parse_module_directive(':-'(module(Name)), _):-
305 seen_module(node(Name)), seen_module.
306parse_module_directive(':-'(module(Name, _Exported)), _):-
307 seen_module(node(Name)), seen_module.
308parse_module_directive(':-'(module(Name, Exported)), Shape):-
309 parse_module_directive, \+ seen_module(node(Name)),
310 assertz(seen_module(node(Name))),
311 list_to_message(Exported, ExportedMessage),
312 atom_concat([Name, ' [shape=', Shape,',label="', Name, '\\n', ExportedMessage, '"]'], NodeDefinition),
313 write(NodeDefinition), write.
314parse_module_directive(':-'(module(Name)), Shape):-
315 \+ seen_module(node(Name)),
316 assertz(seen_module(node(Name))),
317 atom_concat([Name, ' [shape=', Shape,',label="', Name, '"]'], NodeDefinition),
318 write(NodeDefinition), write.
319
320extract_name_file(PathFile, Name, FinalFile):-
321 split_path_file(PathFile, Path, FileName), Path \== '', split_path_file,
322 extract_name_file(FileName, Name, File),
323 atom_concat(Path, File, FinalFile).
324extract_name_file(File, Name, File):-
325 split_file_ext(File, Name, _), split_file_ext.
326extract_name_file(Name, Name, File):-
327 parameter(default_ext(Ext)),
328 atom_concat(Name, Ext, File).
329
330read_use_module_directive(':-'(ensure_loaded(library(Name))), Name, library(Name), []):- read_use_module_directive.
331read_use_module_directive(':-'(ensure_loaded(Path)), Name, FinalFile, []):-
332 extract_name_file(Path, Name, FinalFile), extract_name_file.
333read_use_module_directive(':-'(use_module(library(Name))), Name, library(Name), []):- read_use_module_directive.
334read_use_module_directive(':-'(use_module(Path)), Name, FinalFile, []):-
335 extract_name_file(Path, Name, FinalFile), extract_name_file.
336read_use_module_directive(':-'(use_module(library(Name), Import)), Name, library(Name), Import):- read_use_module_directive.
337read_use_module_directive(':-'(use_module(Path, Import)), Name, FinalFile, Import):-
338 extract_name_file(Path, Name, FinalFile), extract_name_file.
339read_use_module_directive(':-'(use_module(Name, Path, Import)), Name, FinalFile, Import):-
340 nonvar(Path),
341 extract_name_file(Path, _, FinalFile), extract_name_file.
342read_use_module_directive(':-'(use_module(Name, Path, Import)), Name, FinalFile, Import):-
343 var(Path),
344 extract_name_file(Name, _, FinalFile), extract_name_file.
345
346parse_use_module_directive(Module, Directive):-
347 read_use_module_directive(Directive, Name, File, Imported),
348 parse_use_module_directive(Module, Name, File, Imported).
349parse_use_module_directive(Module, Name, _File, _Imported):-
350 seen_module(edge(Module, Name)), seen_module.
351parse_use_module_directive(Module, Name, File, Imported):-
352 \+ seen_module(edge(Module, Name)),
353 assertz(seen_module(edge(Module, Name))),
354 read_module_file(File, Name),
355 list_to_message(Imported, ImportedMessage),
356 atom_concat([Module, ' -> ', Name, ' [label="', ImportedMessage, '"]'], NodeConnection),
357 write(NodeConnection), write.
358
359list_to_message(List, Message):-
360 length(List, Len),
361 parameter(texts(TextCnt)),
362 (Len > TextCnt + 1 ->
363 append(FirstCnt, _, List),
364 length(FirstCnt, TextCnt),
365 append(FirstCnt, ['...'], First)
366 ;
367 First = List
368 ),
369 list_to_message(First, '', Message).
370
371list_to_message([], Message, Message).
372list_to_message([H|T], '', FinalMessage):-
373 term_to_atom(H, HAtom), term_to_atom,
374 list_to_message(T, HAtom, FinalMessage).
375list_to_message([H|T], AccMessage, FinalMessage):-
376 term_to_atom(H, HAtom),
377 atom_concat([AccMessage, '\\n', HAtom], NewMessage),
378 list_to_message(T, NewMessage, FinalMessage).
379
380read_module_file(library(Module), Module):-
381 read_module_file, parse_module_directive(':-'(module(Module, [])), component).
382read_module_file(File, Module):-
383 parameter(depth(MaxDepth)),
384 nb_getval(depth, Depth),
385 MaxDepth > Depth,
386 split_path_file(File, Path, FileName),
387 catch((working_directory(CurDir,Path), open(FileName, read, S)), _, (parse_module_directive(':-'(module(Module, [])), box3d), fail)),
388 NDepth is Depth + 1,
389 nb_setval(depth, NDepth),
390 nb_setval,
391 catch(read(S, Next),_,fail),
392 process(Module, Next),
393 nb_setval(depth, Depth),
394 close(S), working_directory(_,CurDir), working_directory.
395read_module_file(_, _).
396
397/** @pred process(+ _StreamInp_, + _Goal_)
398
399
400
401For every line _LineIn_ in stream _StreamInp_, call
402`call(Goal,LineIn)`.
403
404
405*/
406process(_, end_of_file):-process.
407process(_, Term):-
408 parse_module_directive(Term, box), parse_module_directive, parse_module_directive.
409process(Module, Term):-
410 parse_use_module_directive(Module, Term), parse_use_module_directive, parse_use_module_directive.
411process(Module, Term):-
412 find_explicit_qualification(Module, Term), find_explicit_qualification.
413
414find_explicit_qualification(OwnerModule, ':-'(Module:Goal)):-
415 find_explicit_qualification, explicit_qualification(OwnerModule, Module, Goal).
416find_explicit_qualification(OwnerModule, ':-'(_Head, Body)):-
417 find_explicit_qualification(OwnerModule, Body).
418find_explicit_qualification(OwnerModule, (Module:Goal, RestBody)):-
419 find_explicit_qualification, explicit_qualification(OwnerModule, Module, Goal),
420 find_explicit_qualification(OwnerModule, RestBody).
421find_explicit_qualification(OwnerModule, (_Goal, RestBody)):-
422 find_explicit_qualification, find_explicit_qualification(OwnerModule, RestBody).
423find_explicit_qualification(OwnerModule, Module:Goal):-
424 find_explicit_qualification, explicit_qualification(OwnerModule, Module, Goal).
425find_explicit_qualification(_OwnerModule, _Goal).
426
427explicit_qualification(InModule, ToModule, Goal):-
428 nonvar(Goal), nonvar(ToModule), nonvar,
429 functor(Goal, FunctorName, Arity),
430 \+ seen_module(explicit(InModule, ToModule, FunctorName/Arity)),
431 assertz(seen_module(explicit(InModule, ToModule, FunctorName/Arity))).
432
433explicit_qualification(InModule, ToModule, Goal):-
434 var(Goal), nonvar(ToModule), nonvar,
435 \+ seen_module(explicit(InModule, ToModule, 'DYNAMIC')),
436 assertz(seen_module(explicit(InModule, ToModule, 'DYNAMIC'))).
437
438explicit_qualification(InModule, ToModule, Goal):-
439 nonvar(Goal), var(ToModule), var,
440 functor(Goal, FunctorName, Arity),
441 \+ seen_module(explicit(InModule, 'DYNAMIC', FunctorName/Arity)),
442 assertz(seen_module(explicit(InModule, 'DYNAMIC', FunctorName/Arity))).
443
444explicit_qualification(InModule, ToModule, Goal):-
445 var(Goal), var(ToModule),
446 \+ seen_module(explicit(InModule, 'DYNAMIC', 'DYNAMIC')),
447 assertz(seen_module(explicit(InModule, 'DYNAMIC', 'DYNAMIC'))).
448
449assertz:-
450 seen_module(explicit(InModule, ToModule, _Goal)),
451 \+ seen_module(generate_explicit(InModule, ToModule)),
452 assertz(seen_module(generate_explicit(InModule, ToModule))),
453 all(Goal, seen_module(explicit(InModule, ToModule, Goal)), Goals),
454 list_to_message(Goals, Explicit),
455 atom_concat([InModule, ' -> ', ToModule, ' [label="', Explicit, '",style=dashed]'], NodeConnection),
456 write(NodeConnection), write, write.
457write.
458
459/*
460 functor(Goal, FunctorName, Arity),
461 term_to_atom(FunctorName/Arity, Imported),
462 atom_concat([InModule, ' -> ', ToModule, ' [label="', Imported, '",style=dashed]'], NodeConnection),
463 write(NodeConnection), nl.
464
465 atom_concat([InModule, ' -> ', ToModule, ' [label="DYNAMIC",style=dashed]'], NodeConnection),
466 write(NodeConnection), nl.
467
468 functor(Goal, FunctorName, Arity),
469 term_to_atom(FunctorName/Arity, Imported),
470 atom_concat([InModule, ' -> DYNAMIC [label="', Imported, '",style=dashed]'], NodeConnection),
471 write(NodeConnection), nl.
472
473 atom_concat([InModule, ' -> DYNAMIC [label="DYNAMIC",style=dashed]'], NodeConnection),
474 write(NodeConnection), nl.
475 */
476
477%% @} @}
478
atom_concat(+ As, ? A)
catch( : Goal,+ Exception,+ Action)
close(+ S)
tell(+ S)
Definition: edio.yap:70
working_directory( ?_CurDir_,? NextDir)
yap_flag( ?Param, ?Value)
assertz(+ C)
retractall(+ G)
nb_setval(+ Name,+ Value)
use_module( +Files )
name( A, L)
all( T,+ G,- L)
findall( T,+ G,- L)
Definition: setof.yap:70
nb_getval(+ Name, - Value)
dynamic( + P )
functor( T, F, N)
integer( T)
nonvar( T)
var( T)
make_diagram(+Inputfilename, +Ouputfilename)
make_diagram(+Inputfilename, +Ouputfilename, +Predicate, +Depth, +Extension)
process(+ StreamInp, + Goal)
append(? List1,? List2,? List3)
length(? L,? S)
member(?Element, ?Set) is true when Set is a list, and Element occurs in it
memberchk(+ Element, + Set)