/* File: flrcompileinclude.P -- Workspace wrapper for .fli files
**
** Author(s): kifer
**
** Contact: flora-users@lists.sourceforge.net
**
** Copyright (C) The Research Foundation of SUNY, 2001, 2002
**
** FLORA-2 is free software; you can redistribute it and/or modify it under the
** terms of the GNU Library General Public License as published by the Free
** Software Foundation; either version 2 of the License, or (at your option)
** any later version.
**
** FLORA-2 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 Library General Public License for
** more details.
**
** You should have received a copy of the GNU Library General Public License
** along with FLORA-2; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** $Id: flrwraparound.P,v 1.13 2003/06/18 07:01:34 kifer Exp $
**
*/
:- compiler_options([xpp_on]).
/*
This simple wrapper understands the directives
:- WRAP_DUMP string.
:- WRAP_WITH_WORKSPACE predicate-list.
:- WRAP_STORAGE predicate-list.
:- WRAP_DEBUGMODULE predicate.
:- WRAP_MODULE predicate.
Predicates mentioned in these directives are
recorded and whenever they occur in other directives or rules
they are wrapped accordingly.
:- WRAP_DUMP whatever.
causes the argument to be dumped into the output as is.
The predicates listed in the other directives are wrapped with
FLORA_THIS_WORKSPACE(predicate),
or FLORA_THIS_FDB_STORAGE(predicate), respectively, for further processing
by the gpp preprocessor.
*/
#include "flag_defs_xsb.h"
#include "flora_terms.flh"
#include "flora_porting.flh"
#include "flora_wrap.flh"
:- dynamic wrap_arguments_directive/1.
:- dynamic flora_wraparound_info/2.
:- op(1100,fy,WRAP_WITH_WORKSPACE).
:- op(1100,fy,WRAP_DUMP).
:- op(1100,fy,WRAP_STORAGE).
:- op(1100,fy,WRAP_MODULE).
:- op(1100,fx,WRAP_INDICES).
%%:- op(1100,fx,FL_ARGUMENTS).
:- op(1100,fx,FL_EQUALITY).
:- bootstrap_flora.
/*************************************************************************
flWrapAround(+File)
This is used only in the closure/Makefile
It takes a trailer template and wraps it with the workspace and
flora prefixes. This way the trailer is easier to maintain and understand.
*************************************************************************/
flWrapAround(File) :-
flora_check_filename(File),
( (flora_locate_file(File,INFILE_EXT,InFile), !
; flora_locate_file(File,FLIFILE_EXT,InFile)
)
->
flora_out_filename(InFile,OutFile),
wrapWorkspace(InFile,OutFile)
;
flora_stderr_nl,
flora_error_line("File %s[.%s] does not exist!",
args(File,INFILE_EXT)),
fail
),
!.
wrapWorkspace(InFile,OutFile) :-
telling(PreOutFile),
tell(OutFile),
wrapWorkspace(InFile),
told,
tell(PreOutFile).
%% this one just writes to stdout
wrapWorkspace(InFile) :-
seeing(PreInFile),
flora_set_xpp_options_for_read,
xpp_process_file(InFile,XPP_process,IOportFromProc),
stat_set_flag(CURRENT_INPUT,IOportFromProc),
process_fli_file,
%% Wait, not to leave zombies.
process_control(XPP_process,wait(ExitStatus)),
(ExitStatus==0, !
; flora_error_line('Error while preprocessing %s', InFile)
),
%% Release the file descriptor used to read from cpp.
file_close(IOportFromProc),
flora_clear_xpp_options,
see(PreInFile).
wrapWorkspace(_).
process_fli_file :-
repeat,
read(X),
(X==end_of_file -> true
; process_clause(X)
).
process_fli_file.
process_clause(X) :-
(is_directive(X,WRAP_WITH_WORKSPACE,PredList)
-> intern_predicate_specs(PredList,WRAP_WITH_WORKSPACE)
; is_directive(X,WRAP_INDICES,IndexSpecList)
-> dump_indices_directive(IndexSpecList)
; is_directive(X,WRAP_DUMP,DumpString)
-> writeln(DumpString)
; is_directive(X,WRAP_STORAGE,RuleList)
-> dump_storage_rules(RuleList)
; is_directive(X,WRAP_MODULE,Pred)
-> dump_module_rule(Pred)
; is_directive(X,Directive,PredList)
-> dump_other_directive(Directive,PredList)
; %% assume it is a rule -- no queries
dump_rule(X)
),
!,
fail.
%% Which macro to use for which type of encoding
wrapper_macro(WRAP_WITH_WORKSPACE,'FLORA_THIS_WORKSPACE').
%% tells how to wrap a predicate spec
wrapper(P/A, WrappedSpec, Changed) :- !,
(var(A) -> EncodedA = '$var' ; EncodedA = A),
(flora_wraparound_info(P/EncodedA,EncodingType),
wrapper_macro(EncodingType,WrapperMacroName)
->
flora_concat_items([WrapperMacroName,'(',P,')'],WrappedP),
WrappedSpec = WrappedP/A,
Changed = wrapped
; WrappedSpec = P/A, Changed = notwrapped
).
wrapper(Spec, WrappedSpec, Changed) :-
Spec =.. [P|Args],
(flora_wraparound_info(Spec,EncodingType),
wrapper_macro(EncodingType,WrapperMacroName)
->
flora_concat_items([WrapperMacroName,'(',P,')'],WP),
WrappedSpec =.. [WP|Args], Changed = wrapped
; WrappedSpec = Spec, Changed = notwrapped
).
spec2skeleton(P/A,Skeleton) :- !, functor(Skeleton,P,A).
spec2skeleton(Skeleton,Skeleton).
is_directive((:- WRAP_WITH_WORKSPACE PredList),WRAP_WITH_WORKSPACE,PredList) :- !.
is_directive((:- WRAP_INDICES IndexSpecList), WRAP_INDICES, IndexSpecList) :- !.
is_directive((:- WRAP_DUMP Atom),WRAP_DUMP,Atom) :- !.
is_directive((:- WRAP_STORAGE RuleList),WRAP_STORAGE,RuleList) :- !.
%% for now, only handle simple directives of the form :- Directive PredList.
is_directive(':-'(DirectiveBody),Directive,PredList) :-
DirectiveBody =.. [Directive,PredList], !.
intern_predicate_specs(','(P,Ps),EncodingType) :- !,
intern_predicate_spec(P,EncodingType),
intern_predicate_specs(Ps,EncodingType).
intern_predicate_specs(P,EncodingType) :-
intern_predicate_spec(P,EncodingType).
%% Insert both the p/a form and p(_,...,_) form
%% Arity can also be a variable. In this case, it is treated specially and the
%% predicate spec is inserted simply as p/_.
%% If p/_ is in the flora_compile_trie, then insert p/'$var' and don't insert
%% p(_,...,_)
intern_predicate_spec(P,EncodingType) :-
P = '/'(Name,Arity),
!,
(var(Arity)
-> assert(flora_wraparound_info('/'(Name,'$var'),EncodingType))
; assert(flora_wraparound_info(P,EncodingType))
),
(var(Arity) -> true
; functor(NewP,Name,Arity),
assert(flora_wraparound_info(NewP,EncodingType))
).
%% Spec of the form of the form name(_,...,_)
intern_predicate_spec(P,EncodingType) :-
functor(P,Name,Arity), Arity >= 0,
!,
assert(flora_wraparound_info(P,EncodingType)),
assert(flora_wraparound_info(Name/Arity,EncodingType)).
intern_predicate_spec(P,EncodingType) :-
flora_error_line('[flWrapAround] Invalid predicate specification in a %s directive: %S', arg(EncodingType,P)).
dump_other_directive(Directive, PredSpecs) :-
write(':- '), writeln(Directive),
dump_rule_body(PredSpecs,1),
writeln('.').
dump_indices_directive(IndexSpecList) :-
writeln(':- index'),
dump_index_specs(IndexSpecList).
dump_index_specs(','(Spec,IndexSpecList)) :-
!,
dump_index_spec(Spec),
writeln(','),
dump_index_specs(IndexSpecList).
dump_index_specs(Spec) :- dump_index_spec(Spec), writeln('.').
dump_index_spec(Spec) :-
(Spec = Pred/Arity-ArgNo, !
; abort(('Invalid index specification: ', Spec))),
dump_literal(Pred/Arity,1),
write('-'), write(ArgNo).
dump_storage_rules(','(Rule,Rest)) :- !,
dump_storage_rule(Rule),
dump_storage_rules(Rest).
dump_storage_rules(Rule) :- dump_storage_rule(Rule).
%% A storage rule looks like this: rule(head-predicate/arity,body-predicate)
dump_storage_rule(rule(HeadSpec,TailPred)) :-
dump_storage_rule(rule(HeadSpec,TailPred,fdb)).
dump_storage_rule(rule(HeadSpec,TailPred,Storage)) :-
dump_storage_rule(rule(HeadSpec,TailPred,Storage,no_leading)).
dump_storage_rule(rule(HeadSpec,TailPred,Storage,Leading)) :-
spec2skeleton(HeadSpec,HeadSkeleton),
dump_simple_goal(HeadSkeleton,0,Leading), writeln(' :-'),
indent(1),
( Storage=fld,
write('flora_db_find_base(FLORA_THIS_FLD_STORAGE,')
;
Storage=fdb,
write('flora_db_find_base(FLORA_THIS_FDB_STORAGE,')
),
%% attach tail's functor to Head's variables
HeadSkeleton =.. [_|HeadVars], BodySkeleton =.. [TailPred|HeadVars],
dump_simple_goal(BodySkeleton,0), writeln(').').
dump_module_rule(rule(HeadSpec,TailPred)) :-
spec2skeleton(HeadSpec,HeadSkeleton),
dump_simple_goal(HeadSkeleton,0), writeln(' :-'),
indent(1),
HeadSkeleton =.. [_|HeadVars],
dump_simple_goal(TailPred,0),
write('(FLORA_THIS_MODULE_NAME'),
( HeadVars == [] ->
true
;
write(','),
write_args(HeadVars)
),
writeln(').').
dump_rule((Head :- Body)) :- !,
dump_simple_goal(Head,0),
writeln(' :-'),
dump_rule_body(Body,1),
writeln('.').
%% Headless rule
dump_rule((:- Body)) :- !,
writeln(':- '), dump_rule_body(Body,1), writeln('.').
%% Facts
dump_rule(Head) :-
dump_literal(Head,0),
writeln('.').
dump_rule_body(','(L,Rest),Indent) :- !,
dump_literal(L,Indent), writeln(','),
dump_rule_body(Rest,Indent).
dump_rule_body(';'(Front,Back),Indent) :- !,
indent(Indent), writeln('('),
Indent1 is Indent + 1,
dump_rule_body(Front,Indent1),
nl, indent(Indent), writeln(';'),
dump_rule_body(Back,Indent1),
nl, indent(Indent), write(')').
dump_rule_body('->'(Front,Back),Indent) :- !,
indent(Indent), writeln('('),
Indent1 is Indent + 1,
dump_rule_body(Front,Indent1),
nl, indent(Indent), writeln('->'),
dump_rule_body(Back,Indent1),
nl, indent(Indent), write(')').
dump_rule_body('\+'(Body),Indent) :- !,
indent(Indent), writeln('\+('),
Indent1 is Indent+1,
dump_rule_body(Body,Indent1),
nl, indent(Indent), write(')').
dump_rule_body(not(Body), Indent) :- !,
indent(Indent), writeln('not('),
Indent1 is Indent+1,
dump_rule_body(Body,Indent1),
nl, indent(Indent), write(')').
dump_rule_body(tnot(Body), Indent) :- !,
indent(Indent), writeln('tnot('),
Indent1 is Indent+1,
dump_rule_body(Body,Indent1),
nl, indent(Indent), write(')').
dump_rule_body(call(Body), Indent) :- !,
indent(Indent), writeln('call('),
Indent1 is Indent+1,
dump_rule_body(Body,Indent1),
nl, indent(Indent), write(')').
dump_rule_body(L,Indent) :- dump_literal(L,Indent).
dump_literal(Spec,Indent) :-
( Spec = ','(F,B) -> dump_rule_body(Spec,Indent)
; Spec = ';'(F,B) -> dump_rule_body(Spec,Indent)
; Spec = '\+'(F) -> dump_rule_body(Spec,Indent)
; Spec = 'not'(F) -> dump_rule_body(Spec,Indent)
; Spec = 'tnot'(F) -> dump_rule_body(Spec,Indent)
; Spec = 'call'(F) -> dump_rule_body(Spec,Indent)
; Spec = '->'(F,B) -> dump_rule_body(Spec,Indent)
; dump_simple_goal(Spec, Indent)
).
%% We don't want things like FLORA_THIS_WORKSPACE
%% to appear in quote marks, as it would be with write_canonical/1
%% Simple write/1 won't work either because strings that are arguments
%% to predicates wil then be written without the quotes
dump_simple_goal(Spec, Indent) :-
dump_simple_goal(Spec, Indent, no_leading).
dump_simple_goal(Spec, Indent, Leading) :-
wrapper(Spec,WSpec,Changed),
indent(Indent),
(Changed=notwrapped
-> (WSpec = '/'(P,A) -> write_canonical(P), write('/'), write(A)
; WSpec =.. [P|Args], Args \== [] ->
write_canonical(P), write('('),
( Leading = leading(L) ->
write_args(L),
write(',')
;
true
),
write_args(Args),
write(')')
; write_canonical(WSpec)
)
; %% Wrapped
(WSpec = '/'(P,A) -> write(P), write('/'), write(A)
; WSpec =.. [P|Args], Args \== [] ->
write(P), write('('),
( Leading = leading(L) ->
write_args(L),
write(',')
;
true
),
write_args(Args),
write(')')
; write(WSpec)
)
).
write_args(Args) :-
Args=[First|Rest], !,
((atomic(First); var(First))
-> write_canonical(First)
; dump_simple_goal(First,0)
),
(Rest==[] -> true
; write(','), write_args(Rest)
).
indent(0) :- !.
indent(1) :- !, write(' ').
indent(N) :- N>1, write(' '), N1 is N-1, indent(N1).
flora_out_filename(File,OutFile) :-
parse_filename(File,Dir,Base,Ext),
in2out_extension(Ext,OutExt),
flora_concat_atoms([Dir,Base,'.',OutExt],OutFile).
in2out_extension(INFILE_EXT,DATFILE_EXT) :- !.
in2out_extension(FLIFILE_EXT,FLHFILE_EXT) :- !.
in2out_extension(Ext,_) :-
flora_error_line('[flWrapAround] Unknown extension, %s', Ext).
syntax highlighted by Code2HTML, v. 0.9.1