Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADDED: portray_var/2 and flag auto_name_variables #867

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions boot/init.pl
Original file line number Diff line number Diff line change
Expand Up @@ -999,9 +999,9 @@
!.

:- dynamic
user:portray/1.
user:portray/1, system:portray_var/2.
:- multifile
user:portray/1.
user:portray/1, system:portray_var/2.


/*******************************
Expand Down
67 changes: 67 additions & 0 deletions boot/toplevel.pl
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@
Keep),
create_prolog_flag(toplevel_residue_vars, false, Keep),
create_prolog_flag(toplevel_list_wfs_residual_program, true, Keep),
create_prolog_flag(auto_name_variables, false, Keep),
'$set_debugger_write_options'(print).

%! setup_backtrace
Expand Down Expand Up @@ -840,6 +841,10 @@
),
trim_stacks,
trim_heap,
( BreakLev == 0
-> reset_variable_names
; true
),
repeat,
read_query(Prompt, Query, Bindings),
prompt(_, Old),
Expand Down Expand Up @@ -1283,6 +1288,68 @@
diff21(T2, H1, T1, Diff).


:- multifile system:portray_var/2, user:portray_var/2.
:- dynamic system:portray_var/2, user:portray_var/2.

system:portray_var(Var, Index) :-
predicate_property(user:portray_var(_,_), ssu),
catch(
\+ \+ user:portray_var(Var, Index),
error(existence_error(matching_rule, _), _),
fail
),
!.

system:portray_var(Var, _Index) :-
current_prolog_flag(auto_name_variables, true),
$,
( nb_current('$named_variables', NVars)
-> true
; NVars = [end]
),

var_nth0(Index, NVars, Var),
phrase(portray_var_name(Index), Codes),
format('~s', [Codes]),
nb_linkval('$named_variables', NVars).

var_nth0(N, List, Var) :-
var_nth(List, Var, 0, N).
var_nth(End, Var, N0, N) :-
End = [end],
!,
nb_linkarg(1, End, Var),
nb_setarg(2, End, [end]),
N = N0.
var_nth([H|_], Var, N0, N) :-
H == Var,
!,
N = N0.
var_nth([_|T], Var, N0, N) :-
succ(N0, N1),
var_nth(T, Var, N1, N).

portray_var_name(Index) -->
`__`,
{ divmod(Index, 26, Rank, Letter),
LCode is Letter + 0'A
},
[LCode],
( { Rank > 0, number_codes(Rank, RCodes) }
-> RCodes
; []
).

%! reset_variable_names is det.
%
% Reset the current list of "variables seen" by the Prolog flag
% `auto_name_variables`, causing the next variable it prints to be
% named `__A`. This is called automatically by the toplevel whenever
% a query prompt is issued at break level 0.

reset_variable_names :-
nb_delete('$named_variables').

%! project_constraints(+Bindings, +ResidueVars) is det.
%
% Call <module>:project_attributes/2 if the Prolog flag
Expand Down
5 changes: 5 additions & 0 deletions customize/init.pl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@

% :- set_prolog_flag(toplevel_print_anon, false).

% If you want unnamed variables to be printed using names (__A, __B)
% instead of ids (_1246, _1248).

% :- set_prolog_flag(auto_name_variables, true).

% If you do not want the tracer to stop at at the exit port.

% :- leash(-exit).
Expand Down
18 changes: 17 additions & 1 deletion man/builtin.doc
Original file line number Diff line number Diff line change
Expand Up @@ -6314,7 +6314,8 @@ current priority.
\termitem{portrayed}{Bool}
If \const{true}, the hook portray/1 is called before printing a term
that is not a variable. If portray/1 succeeds, the term is considered
printed. See also print/1. The default is \const{false}. This option
printed. Similarly, the hook portray_var/3 is called before printing
a variable. See also print/1. The default is \const{false}. This option
is an extension to the ISO write_term options.

\termitem{priority}{Integer}
Expand Down Expand Up @@ -6472,6 +6473,21 @@ is not a variable print/1 first calls portray/1 using the term as
argument. For lists, only the list as a whole is given to portray/1. If
portray/1 succeeds print/1 assumes the term has been written.

\predicate{portray_var}{3}{+Var, +Id, +WriteOptions}
A dynamic predicate, which can be defined by the user to change the
behavior of print/1 on unbound variables. It is used by the Prolog flag
\prologflag{auto_name_variables} to print variables with names. If defined
by the user, it will be called before the auto_name_variables functionality
regardless of the state of that flag, and passed the variable (which the
hook should be careful not to instantiate), the variable's ID (the number
that would be printed following an underscore) and the options to write_term/2
that caused it to be printed. If portray_var/3 fails, Prolog will fall back
to the \prologflag{auto_name_variables} functionality if enabled, or otherwise
just print the default numeric variable ID following an underscore.

This predicate must be defined using SSU (=>)/2 rules, to avoid accidental
instantiation of the variable being portrayed.

\predicate[ISO]{read}{1}{-Term}
Read the next \textbf{Prolog term} from the current input stream and
unify it with \arg{Term}. On reaching end-of-file \arg{Term} is unified
Expand Down
10 changes: 10 additions & 0 deletions man/overview.doc
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,13 @@ definition is more practical.}
Set if Prolog was started with a prolog file as argument. Used by
e.g., edit/0 to edit the initial file.

\prologflagitem{auto_name_variables}{bool}{rw}
If \const{true}, variables printed with the \const{portray(true)} option
of write_term/2 will be tracked and named by identity in the order they
appear, in the sequence (\const{__A} .. \const{__Z}, \const{__A1} ..
\const{__Z1}, etc). The sequence will be reset every time a query prompt
is issued at break level 0.

\prologflagitem{autoload}{atom}{rw}
This flag controls autoloading predicates based on autoload/1 and
autoload/2 as well as predicates from \jargon{autoload libraries}.
Expand Down Expand Up @@ -2299,6 +2306,9 @@ portability.
\begin{itemlist}
\item [portray/1]
Hook into write_term/3 to alter the way terms are printed (ISO).
\item [portray_var/3]
Extension to the portray/1 functionality to alter the way variables
are printed.
\item [message_hook/3]
Hook into print_message/2 to alter the way system messages are printed
(Quintus/SICStus).
Expand Down
1 change: 1 addition & 0 deletions src/pl-global.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ struct PL_global_data
Procedure prolog_trace_interception4;
Procedure prolog_break_hook6; /* prolog:break_hook/6 */
Procedure portray; /* portray/1 */
Procedure portray_var2; /* system:portray_var/2 */
Procedure dcall1; /* $call/1 */
Procedure call3; /* call/3*/
Procedure setup_call_catcher_cleanup4; /* setup_call_catcher_cleanup/4 */
Expand Down
24 changes: 17 additions & 7 deletions src/pl-write.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ typedef struct
} write_options;

#if USE_LD_MACROS
#define var_index_ptr(p) LDFUNC(var_index_ptr, p)
#define enterPortray(_) LDFUNC(enterPortray, _)
#define leavePortray(_) LDFUNC(leavePortray, _)
#endif /*USE_LD_MACROS*/
Expand All @@ -96,8 +97,8 @@ static void leavePortray(void);

#undef LDFUNC_DECLARATIONS

char *
var_name_ptr(DECL_LD Word p, char *name)
static int64_t
var_index_ptr(DECL_LD Word p)
{ size_t iref;

deRef(p);
Expand All @@ -106,8 +107,12 @@ var_name_ptr(DECL_LD Word p, char *name)
iref = ((Word)p - (Word)lBase)*2+1;
else
iref = ((Word)p - (Word)gBase)*2;
return (int64_t) iref;
}

Ssprintf(name, "_%lld", (int64_t)iref);
char *
var_name_ptr(DECL_LD Word p, char *name)
{ Ssprintf(name, "_%lld", var_index_ptr(p));

return name;
}
Expand Down Expand Up @@ -1315,7 +1320,9 @@ callPortray(term_t arg, int prec, write_options *options)
if ( GD->cleaning > CLN_PROLOG )
fail; /* avoid dangerous callbacks */

if ( options->portray_goal )
if ( PL_is_variable(arg) )
{ pred = _PL_predicate("portray_var", 2, "system", &GD->procedures.portray_var2);
} else if ( options->portray_goal )
{ pred = _PL_predicate("call", 3, "user", &GD->procedures.call3);
} else
{ pred = _PL_predicate("portray", 1, "user", &GD->procedures.portray);
Expand All @@ -1334,7 +1341,11 @@ callPortray(term_t arg, int prec, write_options *options)
if ( !saveWakeup(&wstate, TRUE) )
return -1;
Scurout = options->out;
if ( options->portray_goal )
if ( PL_is_variable(arg) )
{ av = PL_new_term_refs(2);
PL_put_term(av+0, arg);
PL_put_int64(av+1, var_index_ptr(valTermRef(arg)));
} else if ( options->portray_goal )
{ av = PL_new_term_refs(3);

PL_put_term(av+0, options->portray_goal);
Expand Down Expand Up @@ -1510,8 +1521,7 @@ writeTerm2(term_t t, int prec, write_options *options, bool arg)
atom_t a;
IOSTREAM *out = options->out;

if ( !PL_is_variable(t) &&
true(options, PL_WRT_PORTRAY) )
if ( true(options, PL_WRT_PORTRAY) )
{ switch( callPortray(t, prec, options) )
{ case TRUE:
return TRUE;
Expand Down