View source with raw comments or as raw
    1:- module(scasp_dyncall,
    2          [ scasp/2,                    % :Query, +Options
    3            scasp_query_clauses/2,      % :Query, -Clauses
    4            scasp_model/1,              % -Model
    5            scasp_justification/2,      % -Tree, +Options
    6
    7            scasp_show/2,               % :Query,+What
    8
    9            (scasp_dynamic)/1,          % :Spec
   10            scasp_assert/1,             % :Clause
   11            scasp_assert/2,             % :Clause
   12            scasp_retract/1,            % :Clause
   13            scasp_retractall/1,         % :Head
   14            scasp_abolish/1,            % :PredicateIndicator
   15            (#)/1,                      % :Directive
   16            (#)/2,                      % :Directive, +Pos
   17            (pred)/1,
   18            (show)/1,
   19            (abducible)/1,
   20            (abducible)/2,
   21
   22            (#=)/2,
   23            (#<>)/2,
   24            (#<)/2,
   25            (#>)/2,
   26            (#=<)/2,
   27            (#>=)/2,
   28
   29            op(900, fy, not),
   30            op(950, xfx, ::),           % pred not x :: "...".
   31            op(1200, fx, #),
   32            op(1150, fx, pred),
   33            op(1150, fx, show),
   34            op(1150, fx, abducible),
   35            op(1150, fx, scasp_dynamic),
   36            op(700, xfx, #=),
   37            op(700, xfx, #<>),
   38            op(700, xfx, #<),
   39            op(700, xfx, #>),
   40            op(700, xfx, #=<),
   41            op(700, xfx, #>=)
   42          ]).   43:- use_module(compile).   44:- use_module(embed).   45:- use_module(common).   46:- use_module(modules).   47:- use_module(source_ref).   48:- use_module(listing).   49:- use_module(clp/clpq, [apply_clpq_constraints/1]).   50:- use_module(pr_rules, [process_pr_pred/5]).   51:- use_module(predicates, [prolog_builtin/1,
   52                           clp_builtin/1, clp_interval/1]).   53
   54:- use_module(library(apply), [maplist/3, exclude/3, maplist/2]).   55:- use_module(library(assoc), [empty_assoc/1, get_assoc/3, put_assoc/4]).   56:- use_module(library(error),
   57              [ instantiation_error/1,
   58                permission_error/3,
   59                type_error/2,
   60                must_be/2
   61              ]).   62:- use_module(library(lists), [member/2, append/3]).   63:- use_module(library(modules),
   64              [in_temporary_module/3, current_temporary_module/1]).   65:- use_module(library(option), [option/2]).   66:- use_module(library(ordsets), [ord_intersect/2, ord_union/3]).   67:- use_module(library(prolog_code), [pi_head/2]).   68
   69:- meta_predicate
   70    scasp(0, +),
   71    scasp_show(:, +),
   72    scasp_query_clauses(:, -),
   73    scasp_dynamic(:),
   74    scasp_assert(:),
   75    scasp_retract(:),
   76    scasp_retractall(:),
   77    scasp_abolish(:),
   78    pred(:),
   79    show(:),
   80    abducible(:).

This predicate assembles the clauses that are reachable from a given goal.

Issues:

 scasp(:Query) is nondet
 scasp(:Query, +Options) is nondet
Prove query using s(CASP) semantics. This performs the following steps:

Options are passed to scasp_compile/2. Other options processed:

model(-Model)
Unify Model with the s(CASP) model, a list of model terms. See scasp_model/1.
tree(-Tree)
Unify Tree with the s(CASP) justification tree. See scasp_justification/2 for details.
source(Boolean)
When false, do not include source origin terms into the final tree.
  123scasp(Query, Options) :-
  124    Query = SrcModule:_,
  125    scasp_query_clauses(Query, Clauses0),
  126    expand_program(SrcModule,  Clauses0, Clauses1, Query, Query1),
  127    maplist(qualify, Clauses1, Clauses2),
  128    qualify_query(Query1, SrcModule:QQuery),
  129    q_expand_program(SrcModule, Clauses2, Clauses, QQuery, QQuery1),
  130    in_temporary_module(
  131        Module,
  132        prepare(Clauses, Module, Options),
  133        scasp_call_and_results(Module:QQuery1, SrcModule, Options)).
  134
  135prepare(Clauses, Module, Options) :-
  136    scasp_compile(Module:Clauses, Options),
  137    (   option(write_program(_), Options)
  138    ->  scasp_portray_program(Module:Options)
  139    ;   true
  140    ).
  141
  142qualify_query(M:Q0, M:Q) :-
  143    qualify(Q0, M, Q1),
  144    intern_negation(Q1, Q).
  145
  146expand_program(SrcModule, Clauses, Clauses1, QQuery, QQuery1) :-
  147    current_predicate(SrcModule:scasp_expand/4),
  148    SrcModule:scasp_expand(Clauses, Clauses1, QQuery, QQuery1),
  149    !.
  150expand_program(_, Clauses, Clauses, QQuery, QQuery).
  151
  152q_expand_program(SrcModule, Clauses, Clauses1, QQuery, QQuery1) :-
  153    current_predicate(SrcModule:scasp_expand_program/4),
  154    SrcModule:scasp_expand_program(Clauses, Clauses1, QQuery, QQuery1),
  155    !.
  156q_expand_program(_, Clauses, Clauses, QQuery, QQuery).
  157
  158
  159scasp_call_and_results(Query, SrcModule, Options) :-
  160    scasp_embed:scasp_call(Query),
  161    (   option(model(Model), Options)
  162    ->  scasp_model(SrcModule:Model)
  163    ;   true
  164    ),
  165    (   option(tree(Tree), Options)
  166    ->  scasp_justification(SrcModule:Tree, Options)
  167    ;   true
  168    ).
 scasp_show(:Query, +What)
Show some aspect of the translated s(CASP) program. Currently What is one of:
code(Options)
Show the collected program. By default shows the query and user program. To show only the integrity constraints, use:
?- scasp_show(Query, code(user(false), constraints(true))).
  182scasp_show(Query, What) :-
  183    What =.. [Type|Options],
  184    scasp_show(Query, Type, Options).
  185
  186scasp_show(Query, code, Options) =>
  187    Query = SrcModule:_,
  188    scasp_query_clauses(Query, Clauses0),
  189    expand_program(SrcModule,  Clauses0, Clauses1, Query, Query1),
  190    maplist(qualify, Clauses1, Clauses2),
  191    qualify_query(Query1, SrcModule:QQuery),
  192    q_expand_program(SrcModule, Clauses2, Clauses, QQuery, _QQuery1),
  193    in_temporary_module(
  194        Module,
  195        prepare(Clauses, Module, []),
  196        scasp_portray_program(Module:[source_module(SrcModule)|Options])).
 scasp_query_clauses(:Query, -Clauses) is det
Arguments:
Clauses- is a list of source(ClauseRef, Clause).
  202:- det(scasp_query_clauses/2).  203
  204scasp_query_clauses(Query, Clauses) :-
  205    query_callees(Query, Callees0),
  206    include_global_constraint(Callees0, Constraints, Callees),
  207    findall(Clause, scasp_clause(Callees, Clause), Clauses, Constraints).
  208
  209scasp_clause(Callees, source(ClauseRef, M:(Head:- Body))) :-
  210    member(PI, Callees),
  211    pi_head(PI, M:Head),
  212    @(clause(Head, Body, ClauseRef), M).
  213
  214qualify(source(Ref, Clause), Q) =>
  215    Q = source(Ref, QClause),
  216    qualify(Clause, QClause).
  217qualify(M:(Head :- true), Q) =>
  218    qualify(Head, M, Q).
  219qualify(M:(Head :- Body), Q) =>
  220    qualify((Head:-Body), M, Q).
  221qualify(M:(:- Body), Q) =>
  222    Q = (:- Constraint),
  223    qualify(Body, M, Constraint).
  224
  225qualify(-(Head), M, Q) =>
  226    Q = -QHead,
  227    qualify(Head, M, QHead).
  228qualify(not(Head), M, Q) =>
  229    Q = not(QHead),
  230    qualify(Head, M, QHead).
  231qualify(findall(Templ, Head, List), M, Q) =>
  232    Q = findall(Templ, QHead, List),
  233    qualify(Head, M, QHead).
  234qualify((A,B), M, Q) =>
  235    Q = (QA,QB),
  236    qualify(A, M, QA),
  237    qualify(B, M, QB).
  238qualify((A:-B), M, Q) =>
  239    Q = (QA:-QB),
  240    qualify(A, M, QA),
  241    qualify(B, M, QB).
  242qualify(G, M, Q), callable(G) =>
  243    (   built_in(G)
  244    ->  Q = G
  245    ;   implementation(M:G, Callee),
  246        encoded_module_term(Callee, Q)
  247    ).
 query_callees(:Query, -Callees) is det
True when Callees is a list of predicate indicators for predicates reachable from Query.
Arguments:
Callees- is an ordered set.
  256query_callees(M:Query, Callees) :-
  257    findall(Call, body_calls_pi(Query,M,Call), Calls0),
  258    sort(Calls0, Calls),
  259    callee_graph(Calls, Callees).
  260
  261body_calls_pi(Query, M, PI) :-
  262    body_calls(Query, M, Call),
  263    pi_head(PI, Call).
  264
  265callee_graph(Preds, Nodes) :-
  266    empty_assoc(Expanded),
  267    callee_closure(Preds, Expanded, Preds, Nodes0),
  268    sort(Nodes0, Nodes).
  269
  270callee_closure([], _, Preds, Preds).
  271callee_closure([H|T], Expanded, Preds0, Preds) :-
  272    (   get_assoc(H, Expanded, _)
  273    ->  callee_closure(T, Expanded, Preds0, Preds)
  274    ;   put_assoc(H, Expanded, true, Expanded1),
  275        pi_head(H, Head),
  276        predicate_callees(Head, Called),
  277        exclude(expanded(Expanded1), Called, New),
  278        append(New, T, Agenda),
  279        append(New, Preds0, Preds1),
  280        callee_closure(Agenda, Expanded1, Preds1, Preds)
  281    ).
  282
  283expanded(Assoc, PI) :-
  284    get_assoc(PI, Assoc, _).
 include_global_constraint(+Callees, -Constraints, -AllCallees) is det
  288include_global_constraint(Callees0, Constraints, Callees) :-
  289    include_global_constraint(Callees0, Callees, [], Constraints).
  290
  291include_global_constraint(Callees0, Callees, Constraints0, Constraints) :-
  292    global_constraint(Constraint),
  293    Constraint = source(_, Rule),       % Rule = M:(:-Body)
  294    \+ ( member(source(_, Rule0), Constraints0),
  295         Rule =@= Rule0
  296       ),
  297    Rule = M:(:-Body),
  298    query_callees(M:Body, Called),
  299    ord_intersect(Callees0, Called),
  300    !,
  301    ord_union(Callees0, Called, Callees1),
  302    include_global_constraint(Callees1, Callees,
  303                              [Constraint|Constraints0], Constraints).
  304include_global_constraint(Callees, Callees, Constraints, Constraints).
  305
  306
  307global_constraint(source(Ref, M:(:- Body))) :-
  308    (   current_temporary_module(M)
  309    ;   current_module(M)
  310    ),
  311    current_predicate(M:(-)/0),
  312    \+ predicate_property(M:(-), imported_from(_)),
  313    @(clause(-, Body, Ref), M).
 predicate_callees(:Head, -Callees) is det
True when Callees is the list of direct callees from Head. Each callee is a predicate indicator.
  320:- dynamic predicate_callees_c/4.  321
  322predicate_callees(M:Head, Callees) :-
  323    predicate_callees_c(Head, M, Gen, Callees0),
  324    predicate_generation(M:Head, Gen),
  325    !,
  326    Callees = Callees0.
  327predicate_callees(M:Head, Callees) :-
  328    module_property(M, class(temporary)),
  329    !,
  330    predicate_callees_nc(M:Head, Callees).
  331predicate_callees(M:Head, Callees) :-
  332    retractall(predicate_callees_c(Head, M, _, _)),
  333    predicate_callees_nc(M:Head, Callees0),
  334    predicate_generation(M:Head, Gen),
  335    assertz(predicate_callees_c(Head, M, Gen, Callees0)),
  336    Callees = Callees0.
  337
  338predicate_callees_nc(Head, Callees) :-
  339    findall(Callee, predicate_calls(Head, Callee), Callees0),
  340    sort(Callees0, Callees).
  341
  342predicate_calls(Head0, PI) :-
  343    generalise(Head0, M:Head),
  344    @(clause(Head, Body), M),
  345    body_calls(Body, M, Callee),
  346    pi_head(PI, Callee).
  347
  348body_calls(Goal, _M, _), var(Goal) =>
  349    instantiation_error(Goal).
  350body_calls(true, _M, _) => fail.
  351body_calls((A,B), M, Callee) =>
  352    (   body_calls(A, M, Callee)
  353    ;   body_calls(B, M, Callee)
  354    ).
  355body_calls(not(A), M, Callee) =>
  356    body_calls(A, M, Callee).
  357body_calls(findall(_,G,_), M, Callee) =>
  358    body_calls(G, M, Callee).
  359body_calls(N, M, Callee), rm_classic_negation(N,A) =>
  360    body_calls(A, M, Callee).
  361body_calls(M:A, _, Callee), atom(M) =>
  362    body_calls(A, M, Callee).
  363body_calls(G, _M, _CalleePM), callable(G), built_in(G) =>
  364    fail.
  365body_calls(G, M, CalleePM), callable(G) =>
  366    implementation(M:G, Callee0),
  367    generalise(Callee0, Callee),
  368    (   predicate_property(Callee, interpreted),
  369        \+ predicate_property(Callee, meta_predicate(_))
  370    ->  pm(Callee, CalleePM)
  371    ;   \+ predicate_property(Callee, _)
  372    ->  pm(Callee, CalleePM)            % undefined
  373    ;   pi_head(CalleePI, Callee),
  374        permission_error(scasp, procedure, CalleePI)
  375    ).
  376body_calls(G, _, _) =>
  377    type_error(callable, G).
  378
  379built_in(Head) :-
  380    prolog_builtin(Head).
  381built_in(Head) :-
  382    clp_builtin(Head).
  383built_in(Head) :-
  384    clp_interval(Head).
  385built_in(_ is _).
  386built_in(findall(_,_,_)).
  387
  388rm_classic_negation(-Goal, Goal) :-
  389    !.
  390rm_classic_negation(Goal, PGoal) :-
  391    functor(Goal, Name, _),
  392    atom_concat(-, Plain, Name),
  393    Goal  =.. [Name|Args],
  394    PGoal =.. [Plain|Args].
  395
  396pm(P, P).
  397pm(M:P, M:MP) :-
  398    intern_negation(-P, MP).
  399
  400implementation(M0:Head, M:Head) :-
  401    predicate_property(M0:Head, imported_from(M1)),
  402    !,
  403    M = M1.
  404implementation(Head, Head).
  405
  406generalise(M:Head0, Gen), atom(M) =>
  407    Gen = M:Head,
  408    generalise(Head0, Head).
  409generalise(-Head0, Gen) =>
  410    Gen = -Head,
  411    generalise(Head0, Head).
  412generalise(Head0, Head) =>
  413    functor(Head0, Name, Arity),
  414    functor(Head, Name, Arity).
  415
  416predicate_generation(Head, Gen) :-
  417    predicate_property(Head, last_modified_generation(Gen0)),
  418    !,
  419    Gen = Gen0.
  420predicate_generation(_, 0).
  421
  422
  423		 /*******************************
  424		 *   MANIPULATING THE PROGRAM	*
  425		 *******************************/
 scasp_dynamic(:Spec) is det
Declare a predicates as dynamic or thread_local. Usage patterns:

:- scasp_dynamic p/1. :- scasp_dynamic p/1 as shared.

  434scasp_dynamic(M:Spec) :-
  435    scasp_dynamic(Spec, M, private).
  436scasp_dynamic(M:(Spec as Scoped)) :-
  437    scasp_dynamic(Spec, M, Scoped).
  438
  439scasp_dynamic((A,B), M, Scoped) =>
  440    scasp_dynamic(A, M, Scoped),
  441    scasp_dynamic(B, M, Scoped).
  442scasp_dynamic(Name/Arity, M, Scoped) =>
  443    atom_concat(-, Name, NName),
  444    (   Scoped == shared
  445    ->  dynamic((M:Name/Arity,
  446                 M:NName/Arity))
  447    ;   thread_local((M:Name/Arity,
  448                     M:NName/Arity))
  449    ).
  450
  451:- multifile system:term_expansion/2.  452
  453system:term_expansion((:- scasp_dynamic(Spec)), Directives) :-
  454    phrase(scasp_dynamic_direcives(Spec), Directives).
  455
  456scasp_dynamic_direcives(Spec as Scope) -->
  457    !,
  458    scasp_dynamic_direcives(Spec, Scope).
  459scasp_dynamic_direcives(Spec) -->
  460    !,
  461    scasp_dynamic_direcives(Spec, private).
  462
  463scasp_dynamic_direcives(Var, _) -->
  464    { var(Var), !, fail }.
  465scasp_dynamic_direcives((A,B), Scope) -->
  466    scasp_dynamic_direcives(A, Scope),
  467    scasp_dynamic_direcives(B, Scope).
  468scasp_dynamic_direcives(Name/Arity, Scope) -->
  469    { atom_concat(-, Name, NName) },
  470    (   {Scope == shared}
  471    ->  [(:- dynamic((Name/Arity, NName/Arity)))]
  472    ;   [(:- thread_local((Name/Arity, NName/Arity)))]
  473    ).
 scasp_assert(:Clause) is det
 scasp_retract(:Clause) is nondet
 scasp_retractall(:Head) is det
Wrappers for assertz/1, retract/1 and retractall/1 that deal with sCASP terms which may have a head or body terms that are wrapped in -(Term), indicating classical negation. Also deals with global constraints written in any of these formats:
  488scasp_assert(Clause) :-
  489    scasp_assert(Clause, false).
  490
  491scasp_assert(M:(-Head :- Body0), Pos) =>
  492    intern_negation(-Head, MHead),
  493    expand_goal(Body0, Body),
  494    scasp_assert_(M:(MHead :- Body), Pos).
  495scasp_assert(M:(-Head), Pos) =>
  496    intern_negation(-Head, MHead),
  497    scasp_assert_(M:(MHead), Pos).
  498scasp_assert(M:(:- Body0), Pos) =>
  499    expand_goal(Body0, Body),
  500    scasp_assert_(M:((-) :- Body), Pos).
  501scasp_assert(M:(false :- Body0), Pos) =>
  502    expand_goal(Body0, Body),
  503    scasp_assert_(M:((-) :- Body), Pos).
  504scasp_assert(M:(Head :- Body0), Pos) =>
  505    expand_goal(Body0, Body),
  506    scasp_assert_(M:(Head :- Body), Pos).
  507scasp_assert(Head, Pos) =>
  508    scasp_assert_(Head, Pos).
  509
  510scasp_assert_(Clause, false) =>
  511    assertz(Clause).
  512scasp_assert_(Clause, Pos) =>
  513    assertz(Clause, Ref),
  514    assertz(scasp_dynamic_clause_position(Ref, Pos)).
  515
  516scasp_assert_into(M, Pos, Rule) :-
  517    scasp_assert(M:Rule, Pos).
  518
  519scasp_retract(M:(-Head :- Body0)) =>
  520    intern_negation(-Head, MHead),
  521    expand_goal(Body0, Body),
  522    retract(M:(MHead :- Body)).
  523scasp_retract(M:(-Head)) =>
  524    intern_negation(-Head, MHead),
  525    retract(M:(MHead)).
  526scasp_retract(M:(:- Body0)) =>
  527    expand_goal(Body0, Body),
  528    retract(M:((-) :- Body)).
  529scasp_retract(M:(false :- Body0)) =>
  530    expand_goal(Body0, Body),
  531    retract(M:((-) :- Body)).
  532scasp_retract(M:(Head :- Body0)) =>
  533    expand_goal(Body0, Body),
  534    retract(M:(Head :- Body)).
  535scasp_retract(Head) =>
  536    retract(Head).
  537
  538scasp_retractall(M:(-Head)) =>
  539    intern_negation(-Head, MHead),
  540    retractall(M:MHead).
  541scasp_retractall(Head) =>
  542    retractall(Head).
 scasp_abolish(:PredicateIndicator) is det
Remove all facts for both PredicateIndicator and its classical negation.
  549scasp_abolish(M:(Name/Arity)) =>
  550    pi_head(Name/Arity, Head),
  551    scasp_retractall(M:Head),
  552    scasp_retractall(M:(-Head)).
  553
  554
  555		 /*******************************
  556		 *          DIRECTIVES		*
  557		 *******************************/
 #(:Directive)
Handle s(CASP) directives. Same as :- Directive.. Provides compatibility with sCASP sources as normally found.
  564#(Directive) :- #(Directive, false).
  565
  566#(M:pred(Spec), _)        => pred(M:Spec).
  567#(M:show(Spec), _)        => show(M:Spec).
  568#(M:abducible(Spec), Pos) => abducible(M:Spec, Pos).
  569
  570pred(M:(Spec :: Template)) =>
  571    process_pr_pred(Spec :: Template, Atom, Children, Cond, Human),
  572    assertz(M:pr_pred_predicate(Atom, Children, Cond, Human)).
  573
  574show(M:PIs) =>
  575    phrase(show(PIs), Clauses),
  576    maplist(assert_show(M), Clauses).
  577
  578assert_show(M, Clause) :-
  579    assertz(M:Clause).
  580
  581show(Var) -->
  582    { var(Var),
  583      instantiation_error(Var)
  584    }.
  585show((A,B)) -->
  586    !,
  587    show(A),
  588    show(B).
  589show(not(PI)) -->
  590    { pi_head(PI, Head) },
  591    [ pr_show_predicate(not(Head)) ].
  592show(PI) -->
  593    { pi_head(PI, Head) },
  594    [ pr_show_predicate(Head) ].
 abducible(:Spec)
Declare Spec, a comma list of heads to be abducible, meaning they can both be in or outside the model.
  601abducible(Spec) :- abducible(Spec, false).
  602
  603abducible(M:(A,B), Pos) =>
  604    abducible(M:A, Pos),
  605    abducible(M:B, Pos).
  606abducible(M:Head, Pos), callable(Head) =>
  607    abducible_rules(Head, Rules),
  608    maplist(scasp_assert_into(M, Pos), Rules).
  609
  610abducible_rules(Head,
  611                [ (Head    :- AHead1),
  612                  (NegHead :- AHead2),
  613                  (AHead1  :- not AHead2),
  614                  (AHead2  :- not AHead1)
  615                ]) :-
  616    abducible_head('abducible$',  Head, AHead1),
  617    abducible_head('abducible$$', Head, AHead2),
  618    intern_negation(-Head, NegHead).
  619
  620abducible_head(Prefix, Head, AHead) :-
  621    format(atom(AHead), '~w~k$', [Prefix, Head]).
  622
  623abducible(Var) -->
  624    { var(Var),
  625      instantiation_error(Var)
  626    }.
  627abducible((A,B)) -->
  628    !,
  629    abducible(A),
  630    abducible(B).
  631abducible(Head) -->
  632    { must_be(callable, Head),
  633      abducible_rules(Head, Clauses)
  634    },
  635    list(Clauses).
  636
  637list([]) --> [].
  638list([H|T]) --> [H], list(T).
  639
  640
  641
  642		 /*******************************
  643		 *            EXPAND		*
  644		 *******************************/
  645
  646user:term_expansion(-Fact, MFact) :-
  647    callable(Fact),
  648    Fact \= _:_,
  649    intern_negation(-Fact, MFact).
  650user:term_expansion((-Head :- Body), (MHead :- Body)) :-
  651    callable(Head),
  652    Head \= _:_,
  653    intern_negation(-Head, MHead).
  654user:term_expansion((false :- Body), ((-) :- Body)).
  655user:term_expansion((:- pred(SpecIn)),
  656                    pr_pred_predicate(Atom, Children, Cond, Human)) :-
  657    process_pr_pred(SpecIn, Atom, Children, Cond, Human).
  658user:term_expansion((:- show(SpecIn)), Clauses) :-
  659    phrase(show(SpecIn), Clauses).
  660user:term_expansion((:- abducible(SpecIn)), Clauses) :-
  661    phrase(abducible(SpecIn), Clauses).
  662user:term_expansion((# pred(SpecIn)),
  663                    pr_pred_predicate(Atom, Children, Cond, Human)) :-
  664    process_pr_pred(SpecIn, Atom, Children, Cond, Human).
  665user:term_expansion((# show(SpecIn)), Clauses) :-
  666    phrase(show(SpecIn), Clauses).
  667user:term_expansion((# abducible(SpecIn)), Clauses) :-
  668    phrase(abducible(SpecIn), Clauses).
  669
  670user:goal_expansion(-Goal, MGoal) :-
  671    callable(Goal),
  672    intern_negation(-Goal, MGoal).
  673
  674
  675		 /*******************************
  676		 *              CLP		*
  677		 *******************************/
 #=(?A, ?B)
 #<>(?A, ?B)
 #<(?A, ?B)
 #>(?A, ?B)
 #>=(?A, ?B)
 #=<(?A, ?B)
Implementation of the s(CASP) constraints. This implementation is normally not used and mostly makes the program analysis work.
  689A #=  B :- apply_clpq_constraints(A #=  B).
  690A #<> B :- apply_clpq_constraints(A #<> B).
  691A #<  B :- apply_clpq_constraints(A #<  B).
  692A #>  B :- apply_clpq_constraints(A #>  B).
  693A #=< B :- apply_clpq_constraints(A #=< B).
  694A #>= B :- apply_clpq_constraints(A #>= B).
  695
  696
  697		 /*******************************
  698		 *            SOURCE		*
  699		 *******************************/
  700
  701:- multifile
  702    prolog_clause:unify_goal/5.  703
  704prolog_clause:unify_goal(scasp(RGoal, Options),
  705                         scasp(CGoal, Options),
  706                         _Module,
  707                         TermPos, TermPos) :-
  708    intern_negation(RGoal, RGoal2),
  709    RGoal2 =@= CGoal.
  710
  711
  712		 /*******************************
  713		 *            SANDBOX		*
  714		 *******************************/
  715
  716:- multifile
  717    sandbox:safe_meta_predicate/1.  718
  719% scasp/1 is safe as it only allows for pure Prolog predicates
  720% and limited arithmetic.  Note that this does allow calling e.g.
  721% member/2. s(CASP) does not allow for calling _qualified goals,
  722% lists:member(...),
  723
  724sandbox:safe_meta(scasp_dyncall:scasp(_, _), [])