% -----------------------------------------------------------------------------
%  (C) Altran Praxis Limited
% -----------------------------------------------------------------------------
% 
%  The SPARK toolset is free software; you can redistribute it and/or modify it
%  under terms of the GNU General Public License as published by the Free
%  Software Foundation; either version 3, or (at your option) any later
%  version. The SPARK toolset is distributed in the hope that it will be
%  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
%  Public License for more details. You should have received a copy of the GNU
%  General Public License distributed with the SPARK toolset; see file
%  COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
%  the license.
% 
% =============================================================================


%###############################################################################
% PURPOSE
%-------------------------------------------------------------------------------
% Provides access to all information related to rules. This information
% will be retrieved from the available rule files.
%###############################################################################


%###############################################################################
% MODULE
%###############################################################################

:- module(data__rules, [get_rule/8,
                        add_rule/8,

                        prune_rule/8,

                        replace_rule/3,
                        nonground_replace_rule/4,
                        inference_rule/3,
                        user_inference_rule/3,
                        user_rewrite_rule/4]).


%###############################################################################
% DEPENDENCIES
%###############################################################################

:- use_module('data__formats.pro', [add_state/2,
                                    add_type/2]).


%###############################################################################
% TYPES
%###############################################################################

:- add_type('RuleId',
            ['Atom',
             'Functor1']).

:- add_type('RuleSource',
            [rls,
             rlu]).

% Logical descriptions, affecting the legal applicability of rules.
:- add_type('RuleLogic',
            [implication,
             equation]).

% Heuristics, used to guide the application of rules.
:- add_type('RuleHeuristic',
            [hint_direct_introduce,
             hint_conditional_introduce,
             hint_rewrite_one_direction,
             hint_rewrite_both_directions]).


%###############################################################################
% DATA
%###############################################################################

:- add_state(get_rule,
             get_rule('RuleFile_Atom',
                      'RuleId',
                      'RuleSource',
                      'RuleHeuristic',
                      'RuleLogic',
                      'LHS_ExpListList',
                      'RHS_ExpListList',
                      'Condition_ExpList')).
:- dynamic(get_rule/8).


%###############################################################################
% PREDICATES
%###############################################################################


%===============================================================================
% Add.
%===============================================================================

add_rule(RuleFile_Atom,
         RuleId,
         RuleSource,
         RuleHeuristic,
         RuleLogic,
         LHS_ExpList,
         RHS_ExpList,
         Condition_ExpList):-
    % The exact behaviour of the Simplifier is dependent on rule ordering.
    % Thus, the use of assertz here (rather than, say, asserta), is needed
    % to perserve regression testing.
    assertz(get_rule(RuleFile_Atom,
                     RuleId,
                     RuleSource,
                     RuleHeuristic,
                     RuleLogic,
                     LHS_ExpList,
                     RHS_ExpList,
                     Condition_ExpList)),
    !.
%===============================================================================


%===============================================================================
% Prune.
%===============================================================================






















prune_rule(RuleFile_Atom,
           RuleId,
           RuleSource,
           RuleHeuristic,
           RuleLogic,
           LHS_ExpList,
           RHS_ExpList,
           Condition_ExpList):-
    retract(get_rule(RuleFile_Atom,
                     RuleId,
                     RuleSource,
                     RuleHeuristic,
                     RuleLogic,
                     LHS_ExpList,
                     RHS_ExpList,
                     Condition_ExpList)),
    !.
%===============================================================================


%===============================================================================
% Refactor.
%===============================================================================

replace_rule(RuleId, LHS_Exp, RHS_Exp):-
    get_rule(_RuleFile_Atom,
             RuleId,
             rls,
             _RuleHeuristic,
             equation,
             [LHS_Exp],
             [RHS_Exp],
             _Condition_ExpList),
    ground(LHS_Exp),
    ground(RHS_Exp).

nonground_replace_rule(RuleFile_Atom:RuleId,
                       LHS_Exp,
                       RHS_Exp,
                       Condition_ExpList):-
    get_rule(RuleFile_Atom,
             RuleId,
             rls,
             _RuleHeuristic,
             equation,
             [LHS_Exp],
             [RHS_Exp],
             Condition_ExpList),
    \+ ground((LHS_Exp,RHS_Exp)).




inference_rule(RuleFile_Atom:RuleId,
               RHS_Exp,
               LHS_ExpList):-
    get_rule(RuleFile_Atom,
             RuleId,
             rls,
             _RuleHeuristic,
             implication,
             LHS_ExpList,
             [RHS_Exp],
             []).

user_inference_rule(RuleFile_Atom:RuleId, RHS_Exp, LHS_ExpList):-
    get_rule(RuleFile_Atom,
             RuleId,
             rlu,
             _RuleHeuristic,
             implication,
             LHS_ExpList,
             [RHS_Exp],
             []).

user_rewrite_rule(RuleFile_Atom:RuleId, FinalLHS_Exp, FinalRHS_Exp, Condition_ExpList):-
    get_rule(RuleFile_Atom,
             RuleId,
             rlu,
             RuleHeuristic,
             equation,
             [LHS_Exp],
             [RHS_Exp],
             Condition_ExpList),
    switch_bindings(RuleHeuristic, FinalLHS_Exp, FinalRHS_Exp, LHS_Exp,RHS_Exp).





switch_bindings(hint_rewrite_one_direction, FinalLHS_Exp, FinalRHS_Exp, FinalLHS_Exp,FinalRHS_Exp).

switch_bindings(hint_rewrite_both_directions, FinalLHS_Exp, FinalRHS_Exp, FinalLHS_Exp,FinalRHS_Exp).
switch_bindings(hint_rewrite_both_directions, FinalLHS_Exp, FinalRHS_Exp, FinalRHS_Exp, FinalLHS_Exp).
%===============================================================================


%###############################################################################
% END-OF-FILE
