View source with formatted 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)  2016, VU University Amsterdam
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module('$engines',
   36          [ engine_create/3,       % ?Template, :Goal, -Engine
   37            engine_create/4,       % ?Template, :Goal, -Engine, +Options
   38            engine_next_reified/2, % +Engine, -Term
   39            engine_yield/1,        % +Term
   40            engine_self/1,         % -Engine
   41            current_engine/1       % ?Engine
   42          ]).   43
   44:- meta_predicate
   45    engine_create(?, 0, -),
   46    engine_create(?, 0, -, +).   47
   48/** <module> Engine (interactor) support
   49
   50
   51*/
   52
   53%!  engine_create(?Template, :Goal, ?Engine) is det.
   54%!  engine_create(?Template, :Goal, -Engine, +Options) is det.
   55%
   56%   Create a new engine, prepared to run  Goal and return answers as
   57%   instances of Template. Goal is not started.
   58
   59engine_create(Template, Goal, Engine) :-
   60    (   atom(Engine)
   61    ->  '$engine_create'(Engine, Template+Goal, [alias(Engine)])
   62    ;   '$engine_create'(Engine, Template+Goal, [])
   63    ).
   64engine_create(Template, Goal, Engine, Options) :-
   65    '$engine_create'(Engine, Template+Goal, Options).
   66
   67%!  engine_next(+Engine, -Term) is semidet.
   68%
   69%   Switch control to Engine and if engine produces a result, switch
   70%   control  back  and  unify   the    instance   of  Template  from
   71%   engine_create/3,4 with Term. Repeatedly calling engine_next/2 on
   72%   Engine retrieves new instances of  Template by backtracking over
   73%   Goal. Fails of Goal has no  more   solutions.  If Goal raises an
   74%   exception the exception is re-raised by this predicate.
   75
   76%!  engine_next_reified(+Engine, -Term) is det.
   77%
   78%   Similar to engine_next/2 but returning answers in reified form.
   79%   Answers  are  returned  using  the  terms  the(Answer), no, and
   80%   exception(Error).
   81
   82engine_next_reified(Engine, Answer) :-
   83    (   catch(engine_next(Engine, Answer0), Error, true)
   84    ->  (   var(Error)
   85        ->  Answer = the(Answer0)
   86        ;   Answer = exception(Error)
   87        )
   88    ;   Answer = no
   89    ).
   90
   91%!  engine_post(+Engine, +Package) is det.
   92%
   93%   Make the term Package available   for engine_fetch/1 from within
   94%   the engine. At most one term can   be  made available. Posting a
   95%   package does not cause  the  engine   to  wakeup.  Therefore, an
   96%   engine_next/2 call must follow a call to this predicate to make
   97%   the engine fetch the package. The predicate engine_post/3
   98%   combines engine_post/2 and engine_next/2.
   99%
  100%   @error permission_error(post_to, engine, Package) if a package
  101%   was already posted and has not yet been fetched by the engine.
  102
  103%!  engine_post(+Engine, +Package, -Reply) is semidet.
  104%
  105%   Same as engine_next/2, but transfer Term to Engine if Engine
  106%   calls engine_fetch/1. Acts as:
  107%
  108%     ==
  109%     engine_post(Engine, Package, Answer) :-
  110%         engine_post(Engine, Package),
  111%         engine_next(Engine, Answer).
  112%     ==
  113
  114%!  engine_destroy(+Engine) is det.
  115%
  116%   Destroy Engine. Eventually, engine  destruction   will  also  be
  117%   subject to symbol garbage collection.
  118
  119%!  engine_yield(+Term) is det.
  120%
  121%   Make engine_answer/2 return with the given term.
  122
  123engine_yield(Term) :-
  124    '$engine_yield'(Term, 256).
  125
  126%!  engine_self(E) is semidet.
  127%
  128%   True if executed inside engine E
  129
  130engine_self(E) :-
  131    thread_self(E),
  132    is_engine(E).
  133
  134%!  current_engine(?E)
  135%
  136%   True if E is a currently know engine.
  137
  138current_engine(E) :-
  139    thread_property(E, engine(true)).
  140
  141%!  '$engine_yield'(?Term, +Code:integer)
  142%
  143%   Cause PL_next_solution() to return with   Code, providing access
  144%   to  Term  through  PL_yielded().   Can    only   be   called  if
  145%   PL_open_query() is called with PL_Q_ALLOW_YIELD.  Code tells the
  146%   code that controls PL_next_solution() what to   do and the codes
  147%   used must be agreed upon for   a specific application. Code must
  148%   be an integer >= 256. Other  return   codes  are reserved by the
  149%   system.
  150
  151'$engine_yield'(_Term, _Code) :-
  152    '$yield'