1:-module(sokb_parser,
    2	[translate_sokb/2,
    3	 translate_sokb/3,
    4	 commas_to_list/2]).    5
    6
    7:-use_module(library(lists)).    8
    9:-use_module(parser_utils).   10%:- ensure_loaded(solver).
   11:- use_module(solver).   12
   13translate_sokb(Origin,Destination):-
   14    translate_sokb(Origin,Destination,write).
   15translate_sokb(Origin,Destination,Mode):-
   16	parse_sokb(Origin,OriginalSOKB),
   17	dynamics(OriginalSOKB,Dynamic),
   18	rewrite_sokb(OriginalSOKB,RewrittenSOKB),
   19	append(Dynamic,RewrittenSOKB,DynamicRewrittenSOKB),
   20	write_sokb_to_file(Destination,DynamicRewrittenSOKB,Mode).
   21
   22write_sokb_to_file(FileName,SOKB,Mode):-
   23	open(FileName,Mode,Stream),
   24	% If the user has not declared the 'fdet' predicate, declare it as dynamic
   25	% so SCIFF won't fail when invoking it
   26	(member(query([dynamic_predicate(fdet/1)]),SOKB) 
   27        -> true
   28        ;  write(Stream,':- dynamic(fdet/1).'), nl(Stream)
   29    ),
   30	write_sokb_to_stream(SOKB,Stream),
   31	close(Stream).
   32
   33write_sokb_to_stream([],_).
   34write_sokb_to_stream([query([dynamic_predicate(Signature)])|MoreSOKB],Stream):-
   35	!,
   36	write(Stream,':- dynamic('),write(Stream,Signature),
   37	write(Stream,').'),
   38	nl(Stream),
   39	nl(Stream),
   40	write_sokb_to_stream(MoreSOKB,Stream).
   41write_sokb_to_stream([query([Atom])|MoreSOKB],Stream):-
   42	!,
   43	write(Stream,':- '),write(Stream,Atom),write(Stream,'.'),
   44	nl(Stream),
   45	nl(Stream),
   46	write_sokb_to_stream(MoreSOKB,Stream).
   47write_sokb_to_stream([query([Atom|MoreAtoms])|MoreSOKB],Stream):-
   48	write(Stream,':- '),write(Stream,Atom),write(Stream,','),
   49	nl(Stream),
   50	write_tab_list(Stream,MoreAtoms),
   51	write(Stream,'.'),
   52	nl(Stream),
   53	nl(Stream),
   54	write_sokb_to_stream(MoreSOKB,Stream).
   55write_sokb_to_stream([clause([Atom|MoreAtoms])|MoreSOKB],Stream):- !, % SWI does not optimize this cut
   56	write(Stream,Atom),
   57	write(Stream,' :- '),
   58	nl(Stream),
   59	write_tab_list(Stream,MoreAtoms),
   60	write(Stream,'.'),
   61	nl(Stream),
   62	nl(Stream),
   63	write_sokb_to_stream(MoreSOKB,Stream).
   64write_sokb_to_stream([fact([Atom])|MoreSOKB],Stream):-
   65	write(Stream,Atom),write(Stream,'.'),
   66	nl(Stream),
   67	nl(Stream),
   68	write_sokb_to_stream(MoreSOKB,Stream).
   69
   70write_tab_list(_,[]).
   71write_tab_list(Stream,[Atom]):-
   72	!,
   73	indent(Stream),
   74	write(Stream,Atom).
   75write_tab_list(Stream,[Atom|MoreAtoms]):-
   76	indent(Stream),
   77	write(Stream,Atom),
   78	write(Stream,','),
   79	nl(Stream),
   80	write_tab_list(Stream,MoreAtoms).
   81
   82indent(Stream):-
   83	tab_number(N),
   84	write_spaces_to_stream(Stream,N).
   85
   86tab_number(4).
   87
   88write_spaces_to_stream(_,0):-
   89	!.
   90write_spaces_to_stream(Stream,N):-
   91	write(Stream,' '),
   92	N1 is N-1,
   93	write_spaces_to_stream(Stream,N1).
   94
   95read_terms_from_file(FileName,Terms):-
   96	open(FileName,read,Stream),
   97	read_terms_from_stream(Stream,Terms),
   98	close(Stream).
   99
  100read_terms_from_stream(Stream,Terms):-
  101	read_term(Stream,Term,[variable_names(Names)]),
  102	(Term=end_of_file ->
  103	    Terms=[];
  104	    Terms=[t(Term,Names)|Terms1],
  105	    read_terms_from_stream(Stream,Terms1)).
  106
  107parse_sokb(FileName,SOKB):-
  108	read_terms_from_file(FileName,Terms),
  109	parse_terms(Terms,SOKB).
  110
  111parse_terms([],[]).
  112parse_terms([t((:-Query1),Vars)|MoreTerms],[query(Query,Vars)|MoreSOKB]):-
  113	!,
  114	commas_to_list(Query1,Query),
  115	parse_terms(MoreTerms,MoreSOKB).
  116parse_terms([t((Head:-Body1),Vars)|MoreTerms],
  117	    [clause([Head|Body],Vars)|MoreSOKB]):-
  118	!,
  119	commas_to_list(Body1,Body),
  120	parse_terms(MoreTerms,MoreSOKB).
  121parse_terms([t(Term1,Vars)|MoreTerms],[fact(Term,Vars)|MoreSOKB]):-
  122	commas_to_list(Term1,Term),
  123	parse_terms(MoreTerms,MoreSOKB).
  124
  125commas_to_list((A,B),[A|C]):-
  126	!,
  127	commas_to_list(B,C).
  128commas_to_list(A,[A]).
  129
  130rewrite_sokb([],[]).
  131rewrite_sokb([Clause|MoreClauses],[NewClause|MoreNewClauses]):-
  132	rewrite_clause(Clause,NewClause),
  133	rewrite_sokb(MoreClauses,MoreNewClauses).
  134
  135rewrite_clause(Clause,NewClause):-
  136	Clause=..[Type,AtomList,Variables],
  137	rewrite_atom_list(AtomList,Variables,NewAtomList,[],OccurList),
  138	quantifying_atoms(OccurList,Quantifying),
  139	get_quantified_atom_list(Type,NewAtomList,Quantifying,
  140				 QuantifiedAtomList),
  141	NewClause=..[Type,QuantifiedAtomList].
  142
  143rewrite_atom_list([],_,[],OccurList,OccurList).
  144rewrite_atom_list([Atom|MoreAtoms],Variables,[NewAtom|MoreNewAtoms],
  145		  OldOccurList,NewOccurList):-
  146	rewrite_atom(Atom,Variables,NewAtom,OldOccurList,IntOccurList),
  147	rewrite_atom_list(MoreAtoms,Variables,MoreNewAtoms,
  148			  IntOccurList,NewOccurList).
  149
  150rewrite_atom(Atom,Variables,NewAtom,OldOccurList,NewOccurList):-
  151	functor(Atom,Functor,Arity),
  152	Atom=..[Functor|Arguments],
  153	rewrite_arg_list(Arguments,NewArguments,Functor/Arity,
  154			 Variables,OldOccurList,NewOccurList),
  155	NewAtom1=..[Functor|NewArguments],
  156	(is_constraint_functor(Functor)->
  157	NewAtom=clp_constraint(NewAtom1);
  158	NewAtom=NewAtom1).
  159
  160rewrite_arg_list([],[],_,_,OccurList,OccurList).
  161rewrite_arg_list([Arg|MoreArgs],[NewArg|MoreNewArgs],Functor,
  162		 Variables,OldOccurList,NewOccurList):-
  163	rewrite_arg(Arg,NewArg,Functor,Variables,
  164		    OldOccurList,IntOccurList),
  165	rewrite_arg_list(MoreArgs,MoreNewArgs,Functor,
  166			 Variables,IntOccurList,NewOccurList).
  167
  168rewrite_arg(Arg,NewArg,Functor,Variables,OldOccurList,NewOccurList):-
  169	compound(Arg),
  170	!,
  171	Arg=..[Fun|Args],
  172	rewrite_arg_list(Args,NewArgs,Functor,Variables,
  173			 OldOccurList,NewOccurList),
  174	NewArg=..[Fun|NewArgs].
  175rewrite_arg(Arg,VarName,Functor,Variables,OldOccurList,NewOccurList):-
  176	var(Arg),
  177	!,
  178	get_var_name(Variables,Arg,VarName),
  179	update_occur_list(OldOccurList,VarName,Functor,NewOccurList).
  180rewrite_arg(Arg,Arg,_,_,OccurList,OccurList).
  181
  182get_var_name([],_,'_').
  183get_var_name([VarName=Var1|_],Var,VarName):-
  184	Var1==Var,
  185	!.
  186get_var_name([_|MoreVarNames],Var,VarName):-
  187	get_var_name(MoreVarNames,Var,VarName).
  188
  189update_occur_list([],VarName,Functor,[occur(VarName,[Functor])]).
  190update_occur_list([occur(VarName,OldList)|MoreOccurs],
  191		  VarName,Functor,[occur(VarName,NewList)|MoreOccurs]):-
  192	!,
  193	update_occurs(OldList,Functor,NewList).
  194update_occur_list([Occur|MoreOccurs],VarName,Functor,
  195		  [Occur|MoreNewOccurs]):-
  196	update_occur_list(MoreOccurs,VarName,Functor,MoreNewOccurs).
  197
  198update_occurs([],Functor,[Functor]).
  199update_occurs([Functor|Tail],Functor,[Functor|Tail]):-
  200	!.
  201update_occurs([Head|Tail],Functor,[Head|NewTail]):-
  202	update_occurs(Tail,Functor,NewTail).
  203
  204quantifying_atoms([],[]).
  205quantifying_atoms([occur(VarName,OccurList)|MoreOccurs],
  206		  [quant(VarName,forallf)|MoreQuantifyingAtoms]):-
  207	quant_forall(OccurList),
  208	!,
  209	quantifying_atoms(MoreOccurs,MoreQuantifyingAtoms).
  210quantifying_atoms([occur(VarName,OccurList)|MoreOccurs],
  211		  [quant(VarName,existsf)|MoreQuantifyingAtoms]):-
  212	quant_exists(OccurList),
  213	!,
  214	quantifying_atoms(MoreOccurs,MoreQuantifyingAtoms).
  215quantifying_atoms([_|MoreOccurs],QuantifyingAtoms):-
  216	quantifying_atoms(MoreOccurs,QuantifyingAtoms).
  217
  218quant_forall([Occur|MoreOccurs]):-
  219	forall_abducible(Occur),
  220	quant_forall1(MoreOccurs).
  221
  222quant_forall1([]).
  223quant_forall1([Occur|MoreOccurs]):-
  224	forall_abducible(Occur),
  225	!,
  226	quant_forall1(MoreOccurs).
  227quant_forall1([Occur|MoreOccurs]):-
  228	Occur=F/_,
  229	is_constraint_functor(F),
  230	quant_forall1(MoreOccurs).
  231
  232quant_exists([Occur|_]):-
  233	exists_abducible(Occur),
  234	!.
  235quant_exists([_|MoreOccurs]):-
  236	quant_exists(MoreOccurs).
  237
  238
  239forall_abducible(en/2).
  240forall_abducible(noten/2).
  241
  242exists_abducible(e/2).
  243exists_abducible(en/2).
  244exists_abducible(abd/2).
  245
  246
  247get_quantified_atom_list(clause,[Atom|MoreAtoms],Quantifying,
  248			 [Atom|MoreQuantifiedAtoms]):-
  249	append(Quantifying,MoreAtoms,MoreQuantifiedAtoms).
  250get_quantified_atom_list(query,Atoms,Quantifying,QuantifiedAtoms):-
  251	append(Quantifying,Atoms,QuantifiedAtoms).
  252get_quantified_atom_list(fact,Atoms,_,Atoms).
  253
  254
  255get_signatures([],[]).
  256get_signatures([query(_,_)|MoreClauses],Signatures):-
  257	get_signatures(MoreClauses,Signatures).
  258get_signatures([clause([Head|_],_)|MoreClauses],
  259	       [Signature|MoreSignatures]):- !,  % SWI does not optimize this cut
  260	signature(Head,Signature),
  261	get_signatures(MoreClauses,MoreSignatures).
  262get_signatures([fact([Head|_],_)|MoreClauses],
  263	       [Signature|MoreSignatures]):-
  264	signature(Head,Signature),
  265	get_signatures(MoreClauses,MoreSignatures).
  266
  267
  268signature(Term,Functor/L):-
  269	Term=..[Functor|Arguments],
  270	length(Arguments,L).
  271	
  272dynamic_queries([],[]).
  273dynamic_queries([Signature|MoreSignatures],
  274		[query([dynamic_predicate(Signature)])|MoreQueries]):-
  275	dynamic_queries(MoreSignatures,MoreQueries).
  276	       
  277
  278dynamics(SOKB,Dynamics):-
  279	get_signatures(SOKB,Signatures),
  280	remove_duplicates(Signatures,SignatureSet),
  281	dynamic_queries(SignatureSet,Dynamics).
  282
  283
  284remove_duplicates([],[]).
  285remove_duplicates([H|T],L):-
  286	member(H,T),
  287	!,
  288	remove_duplicates(T,L).
  289remove_duplicates([H|T1],[H|T2]):-
  290	remove_duplicates(T1,T2)