View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  1985-2016, University of Amsterdam
    7                              VU University Amsterdam
    8    All rights reserved.
    9
   10    Redistribution and use in source and binary forms, with or without
   11    modification, are permitted provided that the following conditions
   12    are met:
   13
   14    1. Redistributions of source code must retain the above copyright
   15       notice, this list of conditions and the following disclaimer.
   16
   17    2. Redistributions in binary form must reproduce the above copyright
   18       notice, this list of conditions and the following disclaimer in
   19       the documentation and/or other materials provided with the
   20       distribution.
   21
   22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33    POSSIBILITY OF SUCH DAMAGE.
   34*/
   35
   36:- module(toplevel_variables,
   37          [ print_toplevel_variables/0,
   38            verbose_expansion/1,
   39            '$switch_toplevel_mode'/1           % +Mode
   40          ]).   41
   42:- dynamic
   43    verbose/0.   44
   45% define the operator globally
   46:- op(1, fx, user:($)).   47
   48:- public
   49    expand_query/4,         % +Query0, -Query, +Bindings0, -Bindings
   50    expand_answer/2.        % +Answer0, -Answer
 expand_query(+Query0, -Query, +Bindings0, -Bindings) is det
These predicates realise reuse of toplevel variables using the $Var notation. These hooks are normally called by toplevel.pl. If the user defines rules for these hooks in the user module, these implementations may be called (or not) to define the interaction with the user hooks.
   60expand_query(Query, Expanded, Bindings, ExpandedBindings) :-
   61    expand_vars(Bindings, Query, Expanded, NewBindings),
   62    term_variables(Expanded, Free),
   63    delete_bound_vars(Bindings, Free, ExpandedBindings0),
   64    '$append'(ExpandedBindings0, NewBindings, ExpandedBindings),
   65    (   verbose,
   66        Query \=@= Expanded
   67    ->  print_query(Expanded, ExpandedBindings)
   68    ;   true
   69    ).
   70
   71print_query(Query, Bindings) :-
   72    bind_vars(Bindings),
   73    writeq(Query), write('.'), nl,
   74    fail.                           % undo bind_vars/2.
   75print_query(_, _).
   76
   77bind_vars([]).
   78bind_vars([Name=Value|Rest]) :-
   79    Name = Value,
   80    bind_vars(Rest).
 expand_vars(+Bindings, +Query, -Expanded, -NewBindings) is det
Replace $Var terms inside Query by the toplevel variable term and unify the result with Expanded. NewBindings gets Name=Value terms for toplevel variables that are bound to non-ground terms.
Errors
- existence_error(answer_variable, Name)
   90expand_vars(Bindings, Query, Expanded, NewBindings) :-
   91    current_prolog_flag(toplevel_var_size, Count),
   92    Count > 0,
   93    !,
   94    phrase(expand_vars(Bindings, Query, Expanded), NewBindings).
   95expand_vars(Bindings, Query, Query, Bindings).
   96
   97expand_vars(_, Var, Var) -->
   98    { var(Var) },
   99    !.
  100expand_vars(_, Atomic, Atomic) -->
  101    { atomic(Atomic) },
  102    !.
  103expand_vars(Bindings, $(Var), Value) -->
  104    { name_var(Var, Bindings, Name),
  105      (   toplevel_var(Name, Value)
  106      ->  !
  107      ;   throw(error(existence_error(answer_variable, Name), _))
  108      )
  109    },
  110    [ Name = Value ].
  111expand_vars(Bindings, Term, Expanded) -->
  112    { compound_name_arity(Term, Name, Arity),
  113      !,
  114      compound_name_arity(Expanded, Name, Arity),
  115      End is Arity + 1
  116    },
  117    expand_args(1, End, Bindings, Term, Expanded).
  118
  119expand_args(End, End, _, _, _) --> !.
  120expand_args(Arg0, End, Bindings, T0, T) -->
  121    { arg(Arg0, T0, V0),
  122      arg(Arg0, T, V1),
  123      Arg1 is Arg0 + 1
  124    },
  125    expand_vars(Bindings, V0, V1),
  126    expand_args(Arg1, End, Bindings, T0, T).
  127
  128name_var(Var, [VarName = TheVar|_], VarName) :-
  129    Var == TheVar,
  130    !.
  131name_var(Var, [_|T], Name) :-
  132    name_var(Var, T, Name).
  133
  134
  135delete_bound_vars([], _, []).
  136delete_bound_vars([H|T0], Free, [H|T1]) :-
  137    H = (_Name = Value),
  138    v_member(Value, Free),
  139    !,
  140    delete_bound_vars(T0, Free, T1).
  141delete_bound_vars([_|T0], Free, T1) :-
  142    delete_bound_vars(T0, Free, T1).
  143
  144v_member(V, [H|T]) :-
  145    (   V == H
  146    ;   v_member(V, T)
  147    ).
 expand_answer(+Answer0, -Answer) is det
Save toplevel variable bindings.
  153expand_answer(Bindings, Bindings) :-
  154    (   current_prolog_flag(toplevel_var_size, Count),
  155        Count > 0
  156    ->  assert_bindings(Bindings)
  157    ;   true
  158    ).
  159
  160assert_bindings([]).
  161assert_bindings([Var = Value|Tail]) :-
  162    assert_binding(Var, Value),
  163    assert_bindings(Tail).
  164
  165assert_binding(Var, Value) :-
  166    (   ( nonvar(Value) ; attvar(Value))
  167    ->  update_var(Var, Value)
  168    ;   true
  169    ).
  170
  171update_var(Name, Value) :-
  172    current_prolog_flag(toplevel_mode, recursive),
  173    !,
  174    (   nb_current('$topvar', Bindings),
  175        Bindings \== []
  176    ->  true
  177    ;   Bindings = '$topvar'{}
  178    ),
  179    put_dict(Name, Bindings, Value, NewBindings),
  180    b_setval('$topvar', NewBindings).
  181update_var(Name, Value) :-
  182    delete_var(Name),
  183    set_var(Name, Value).
  184
  185delete_var(Name) :-
  186    forall(recorded('$topvar', Name = _, Ref), erase(Ref)).
  187
  188set_var(Name, Value) :-
  189    current_prolog_flag(toplevel_var_size, Count),
  190    !,
  191    (   '$term_size'(Value, Count, _)
  192    ->  recorda('$topvar', Name = Value, _)
  193    ;   true
  194    ).
  195set_var(Name, Value) :-
  196    recorda('$topvar', Name = Value, _).
  197
  198toplevel_var(Var, Binding) :-
  199    current_prolog_flag(toplevel_mode, recursive),
  200    !,
  201    nb_current('$topvar', Bindings),
  202    Bindings \== [],
  203    get_dict(Var, Bindings, Binding).
  204toplevel_var(Var, Binding) :-
  205    recorded('$topvar', Var=Binding).
 $switch_toplevel_mode(+Mode) is det
Migrate the variable database when switching to a new toplevel mode. Alternatively we may decide to wipe it as the semantics of the variables may be slightly different.
  213'$switch_toplevel_mode'(recursive) :-
  214    findall(Name-Value, retract_topvar(Name, Value), Pairs),
  215    dict_pairs(Bindings, '$topvar', Pairs),
  216    b_setval('$topvar', Bindings).
  217'$switch_toplevel_mode'(backtracking) :-
  218    (   nb_current('$topvar', Dict),
  219        Dict \== []
  220    ->  forall(get_dict(Name, Dict, Value),
  221               recorda('$topvar', Name = Value, _))
  222    ),
  223    nb_delete('$topvar').
  224
  225retract_topvar(Name, Value) :-
  226    recorded('$topvar', Name=Value, Ref),
  227    erase(Ref).
 print_toplevel_variables
Print known bindings for toplevel ($Var) variables.
  233print_toplevel_variables :-
  234    (   toplevel_var(Name, Value)
  235    *-> format('$~w =~t~12|~p~n', [Name, Value]),
  236        fail
  237    ;   format('No defined toplevel variables~n')
  238    ).
  239
  240verbose_expansion(on) :-
  241    !,
  242    retractall(verbose),
  243    asserta(verbose).
  244verbose_expansion(off) :-
  245    retractall(verbose)