/* ATNCOMMON.PL */
/*
Introduction.
-------------
This file defines the text representation of ATNs, and those predicates
that don't depend on the internal representation. For how ATNs are
used, see the documentation.
Exported predicates.
--------------------
This file exports these predicates:
assert_atn( T+ )
retractall_atn( Node+ )
atn_reconsult( Filename+ )
'assert_atn(T)' takes the text representation of an ATN and asserts it.
'retractall_atn(Node+)' takes a node term, and retracts all nodes which
match it.
'atn_reconsult(F)' reads and asserts definitions from a file. The file can
also contain directives and Prolog clauses: see the documentation.
*/
/*
Syntax.
-------
Define the following operators to implement the syntax. These are for
PDP-11 compatible Prolog. YOU WILL NEED TO CHANGE THEM FOR DEC-10
COMPATIBLE VERSIONS.
*/
:- op( 255, xfx, :: ).
:- op( 254, xfx, to ).
:- op( 254, fx, to ).
:- op( 254, xfx, if ).
/*
Converting from text to expanded form.
--------------------------------------
See ATNC.PL for a description of expanded form. The main predicate defined
is 'expand( T+, E- ) which expands T (text form) into E (expanded form).
*/
expand( ::(A,B), atn(A,Command,Arcs) ) :-
get_command_and_arcs( B, Command, Arcs ).
/* get_command_and_arcs( Body+, Command-, Arcs- ):
Expand Body into a Command and a list of arcs. These are
the expanded representation of command and arcs as defined
in ATNC.
*/
get_command_and_arcs( (to Arcs), true, Arcs_ ) :-
!,
get_arcs( Arcs, Arcs_ ).
get_command_and_arcs( to(Command,Arcs), Command, Arcs_ ) :-
!,
get_arcs( Arcs, Arcs_ ).
get_command_and_arcs( Command, Command, [] ).
get_arcs( if( Node, to( Cond, Rest ) ), [ Cond, Node | Rest_ ] ) :-
!,
get_arcs( Rest, Rest_ ).
get_arcs( if( Node, Cond ), [ Cond, Node, true, failure ] ) :- !.
get_arcs( Node, [ true, Node ] ).
/*
Loading files.
--------------
This section defines the predicate 'atn_reconsult(File)'.
*/
atn_reconsult( File ) :-
seeing( CIS ),
see( File ), seen,
see( File ),
atn_reconsult_1( '$none' ),
seen,
see( CIS ).
/* atn_reconsult_1( Previous+ ):
Previous is a representation of the previous term in the file.
If there was none, or the term was a directive, Previous
is '$none'.
If the term was a clause, Previous is 'clause(F,A)' where F/A
are the clause's head functor and arity.
If the term was a node definition, Previous is 'atn(F,A)'
where F/A are the node's functor and arity.
Previous is used by 'process_term'. 'process_term' compares
Previous against its first argument, Term. If they are not
a node with the same functor and arity, or a clause with
the same functor and arity, the old definitions will be
deleted.
*/
atn_reconsult_1( Previous ) :-
read( Term ),
(
Term = end_of_file
->
true
;
process_term( Term, Previous, Next ),
atn_reconsult_1( Next )
).
process_term( ?-(Term), _, '$none' ) :-
call( Term ) -> true ; true.
process_term( :-(Term), _, '$none' ) :-
call( Term ) -> true ; true.
process_term( ::(Node,Body), Previous, atn(F,A) ) :-
!,
expand( ::(Node,Body), ATN ),
functor( Node, F, A ),
(
Previous \= atn(F,A)
->
functor( Template, F, A ),
retractall_expanded_atn( Template )
/* Template is the same functor and arity as Node, but all its
arguments are new variables. So retractall_expanded_atn will
delete all nodes with that functor and arity.
*/
;
true
),
assert_expanded_atn( ATN ).
process_term( :-(Head,Tail), Previous, clause(Functor,Arity) ) :-
!,
functor( Head, Functor, Arity ),
(
Previous \= clause(Functor,Arity)
->
abolish( Functor, Arity )
;
true
),
assert( (Head:-Tail) ).
process_term( Head, Previous, Next ) :-
process_term( (Head:-true), Previous, Next ).
assert_atn( ::(A,B) ) :-
expand( ::(A,B), ATN ),
assert_expanded_atn( ATN ).
retractall_atn( ::(A,B) ) :-
expand( ::(A,B), atn(Node,_,_) ),
retractall_expanded_atn( Node ).