162 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			162 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| 
								 | 
							
								/*  Part of SWI-Prolog
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Author:        Jan Wielemaker
							 | 
						||
| 
								 | 
							
								    E-mail:        J.Wielemaker@uva.nl
							 | 
						||
| 
								 | 
							
								    WWW:           http://www.swi-prolog.org
							 | 
						||
| 
								 | 
							
								    Copyright (C): 2010, University of Amsterdam
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								    modify it under the terms of the GNU General Public License
							 | 
						||
| 
								 | 
							
								    as published by the Free Software Foundation; either version 2
							 | 
						||
| 
								 | 
							
								    of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This program 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 along with this library; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    As a special exception, if you link this library with other files,
							 | 
						||
| 
								 | 
							
								    compiled with a Free Software compiler, to produce an executable, this
							 | 
						||
| 
								 | 
							
								    library does not by itself cause the resulting executable to be covered
							 | 
						||
| 
								 | 
							
								    by the GNU General Public License. This exception does not however
							 | 
						||
| 
								 | 
							
								    invalidate any other reasons why the executable file might be covered by
							 | 
						||
| 
								 | 
							
								    the GNU General Public License.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- module(rewrite,
							 | 
						||
| 
								 | 
							
									  [ rewrite/2,			% +Rule, +Input
							 | 
						||
| 
								 | 
							
									    rew_term_expansion/2,
							 | 
						||
| 
								 | 
							
									    rew_goal_expansion/2,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									    op(1200, xfx, (::=))
							 | 
						||
| 
								 | 
							
									  ]).
							 | 
						||
| 
								 | 
							
								:- use_module(library(quintus)).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- meta_predicate
							 | 
						||
| 
								 | 
							
									rewrite(1, +).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	    COMPILATION		*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rew_term_expansion((Rule ::= RuleBody), (Head :- Body)) :-
							 | 
						||
| 
								 | 
							
									translate(RuleBody, Term, Body0),
							 | 
						||
| 
								 | 
							
									simplify(Body0, Body),
							 | 
						||
| 
								 | 
							
									Rule =.. [Name|List],
							 | 
						||
| 
								 | 
							
									Head =.. [Name,Term|List].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rew_goal_expansion(rewrite(To, From), Goal) :-
							 | 
						||
| 
								 | 
							
									nonvar(To),
							 | 
						||
| 
								 | 
							
									To = \Rule,
							 | 
						||
| 
								 | 
							
									callable(Rule),
							 | 
						||
| 
								 | 
							
									Rule =.. [Name|List],
							 | 
						||
| 
								 | 
							
									Goal =.. [Name,From|List].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	      TOPLEVEL		*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%	rewrite(:To, +From)
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%	Invoke the term-rewriting system
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rewrite(M:T, From) :-
							 | 
						||
| 
								 | 
							
									(   var(T)
							 | 
						||
| 
								 | 
							
									->  From = T
							 | 
						||
| 
								 | 
							
									;   T = \Rule
							 | 
						||
| 
								 | 
							
									->  Rule =.. [Name|List],
							 | 
						||
| 
								 | 
							
									    Goal =.. [Name,From|List],
							 | 
						||
| 
								 | 
							
									    M:Goal
							 | 
						||
| 
								 | 
							
									;   match(T, M, From)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								match(Rule, M, From) :-
							 | 
						||
| 
								 | 
							
									translate(Rule, From, Code),
							 | 
						||
| 
								 | 
							
									M:Code.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								translate(Var, Var, true) :-
							 | 
						||
| 
								 | 
							
									var(Var), !.
							 | 
						||
| 
								 | 
							
								translate((\Command, !), Var, (Goal, !)) :- !,
							 | 
						||
| 
								 | 
							
									(   callable(Command),
							 | 
						||
| 
								 | 
							
									    Command =.. [Name|List]
							 | 
						||
| 
								 | 
							
									->  Goal =.. [Name,Var|List]
							 | 
						||
| 
								 | 
							
									;   Goal = rewrite(\Command, Var)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								translate(\Command, Var, Goal) :- !,
							 | 
						||
| 
								 | 
							
									(   callable(Command),
							 | 
						||
| 
								 | 
							
									    Command =.. [Name|List]
							 | 
						||
| 
								 | 
							
									->  Goal =.. [Name,Var|List]
							 | 
						||
| 
								 | 
							
									;   Goal = rewrite(\Command, Var)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								translate(Atomic, Atomic, true) :-
							 | 
						||
| 
								 | 
							
									atomic(Atomic), !.
							 | 
						||
| 
								 | 
							
								translate(C, _, Cmd) :-
							 | 
						||
| 
								 | 
							
									command(C, Cmd), !.
							 | 
						||
| 
								 | 
							
								translate((A, B), T, Code) :-
							 | 
						||
| 
								 | 
							
									(   command(A, Cmd)
							 | 
						||
| 
								 | 
							
									->  !, translate(B, T, C),
							 | 
						||
| 
								 | 
							
									    Code = (Cmd, C)
							 | 
						||
| 
								 | 
							
									;   command(B, Cmd)
							 | 
						||
| 
								 | 
							
									->  !, translate(A, T, C),
							 | 
						||
| 
								 | 
							
									    Code = (C, Cmd)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								translate(Term0, Term, Command) :-
							 | 
						||
| 
								 | 
							
									functor(Term0, Name, Arity),
							 | 
						||
| 
								 | 
							
									functor(Term, Name, Arity),
							 | 
						||
| 
								 | 
							
									translate_args(0, Arity, Term0, Term, Command).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								translate_args(N, N, _, _, true) :- !.
							 | 
						||
| 
								 | 
							
								translate_args(I0, Arity, T0, T1, (C0,C)) :-
							 | 
						||
| 
								 | 
							
									I is I0 + 1,
							 | 
						||
| 
								 | 
							
									arg(I, T0, A0),
							 | 
						||
| 
								 | 
							
									arg(I, T1, A1),
							 | 
						||
| 
								 | 
							
									translate(A0, A1, C0),
							 | 
						||
| 
								 | 
							
									translate_args(I, Arity, T0, T1, C).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								command(0, _) :- !,			% catch variables
							 | 
						||
| 
								 | 
							
									fail.
							 | 
						||
| 
								 | 
							
								command({A}, A).
							 | 
						||
| 
								 | 
							
								command(!, !).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	      SIMPLIFY		*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								%%	simplify(+Raw, -Simplified)
							 | 
						||
| 
								 | 
							
								%
							 | 
						||
| 
								 | 
							
								%	Get rid of redundant `true' goals generated by translate/3.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								simplify(V, V) :-
							 | 
						||
| 
								 | 
							
									var(V), !.
							 | 
						||
| 
								 | 
							
								simplify((A0,B), A) :-
							 | 
						||
| 
								 | 
							
									B == true, !,
							 | 
						||
| 
								 | 
							
									simplify(A0, A).
							 | 
						||
| 
								 | 
							
								simplify((A,B0), B) :-
							 | 
						||
| 
								 | 
							
									A == true, !,
							 | 
						||
| 
								 | 
							
									simplify(B0, B).
							 | 
						||
| 
								 | 
							
								simplify((A0, B0), C) :- !,
							 | 
						||
| 
								 | 
							
									simplify(A0, A),
							 | 
						||
| 
								 | 
							
									simplify(B0, B),
							 | 
						||
| 
								 | 
							
									(   (   A \== A0
							 | 
						||
| 
								 | 
							
									    ;	B \== B0
							 | 
						||
| 
								 | 
							
									    )
							 | 
						||
| 
								 | 
							
									->  simplify((A,B), C)
							 | 
						||
| 
								 | 
							
									;   C = (A,B)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								simplify(X, X).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	       XREF		*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- multifile
							 | 
						||
| 
								 | 
							
									prolog:called_by/2.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								prolog:called_by(rewrite(Spec, _Term), Called) :-
							 | 
						||
| 
								 | 
							
									findall(G+1, sub_term(\G, Spec), Called).
							 |