/* File: flrdecode.P -- Decoder; used for human-readability
**
** Author(s): Michael Kifer
** Contact: flora-users@lists.sourceforge.net
**
** Copyright (C) The Research Foundation of SUNY, 2003
**
** 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.
**
**
**
*/
:- compiler_options([xpp_on]).
#include "flrheader.flh"
#include "flora_terms.flh"
#include "flora_porting.flh"
:- import flatten/2 from basics.
:- import
flora_decode_predicate/6
from flrwrapper.
:- import flora_prlgdef/2 from flrprolog.
:- import flora_opdef/3 from flroperator.
:- import
flora_concat_items/2,
flora_concat_atoms/2,
flora_get_substring/4,
flora_match_substring/5
from flrporting.
:- import
flora_abort/1
from flrutils.
:- export
flora_decode_goal_as_list/2,
flora_decode_goal_as_atom/2,
flora_decode_oid_as_list/2,
flora_decode_oid_as_atom/2,
flora_write_goal/1,
flora_write_goal/2,
flora_write_oid/1,
flora_write_oid/2.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% flora_write_goal %%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_write_goal(Stream,Goal) :-
flora_decode_goal(Goal,Code),
flatten(Code,FlatCode),
write_flat_code(Stream,FlatCode).
%% Write to the currently open output stream
flora_write_goal(Goal) :-
telling(Stream),
flora_write_goal(Stream,Goal).
flora_write_oid(Stream,Goal) :-
flora_decode_oid(Goal,Code),
flatten(Code,FlatCode),
write_flat_code(Stream,FlatCode).
%% Write to the currently open output stream
flora_write_oid(Goal) :-
telling(Stream),
flora_write_oid(Stream,Goal).
write_flat_code(_,[]) :- !.
write_flat_code(Stream,[H|T]) :-
nonvar(H),
H = [_|_],
!,
write_flat_code(Stream,H),
write_flat_code(Stream,T).
write_flat_code(Stream,[H|T]) :-
!,
write(Stream,H),
write_flat_code(Stream,T).
%%%%%%%%%%%%%%%%%%%%%%%% flora_decode_goal_as_atom/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_decode_goal_as_atom(Goal,CodeAtom) :-
flora_decode_goal_as_list(Goal,Code),
flora_concat_items(Code,CodeAtom).
%%%%%%%%%%%%%%%%%%%%%%%% flora_decode_goal_as_list/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_decode_goal_as_list(Goal,FlatCode) :-
flora_decode_goal(Goal,Code),
flatten(Code,FlatCode).
%%%%%%%%%%%%%%%%%%%%%%%% flora_decode_oid_as_atom/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_decode_oid_as_atom(Goal,CodeAtom) :-
flora_decode_oid_as_list(Goal,Code),
flora_concat_items(Code,CodeAtom).
%%%%%%%%%%%%%%%%%%%%%%%% flora_decode_oid_as_list/2 %%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_decode_oid_as_list(Goal,FlatCode) :-
flora_decode_oid(Goal,Code),
flatten(Code,FlatCode).
%%%%%%%%%%%%%%%%%%%%% flora_decode_goal(+Goal,-Code) %%%%%%%%%%%%%%%%%%%%%%%%
%% Returns a (possibly nested) list of atoms whose concatenation %%
%% represents a readable representation of Goal %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
flora_decode_goal(Call,[Call]) :- var(Call).
flora_decode_goal(Call,Code) :-
classify_call(Call, Type,Basename,ArgList,Workspace),
(Type = (basefact,CallType)
-> Code = ['(Checking against base facts) '|RestCode]
; Code = RestCode, Type = CallType
),
( CallType == (hilog)
-> decode_hilog_call(Basename,ArgList,Workspace,RestCode,0)
; CallType == (flogic)
-> decode_molecule(Basename,ArgList,Workspace,RestCode,0)
; CallType == (inheritance)
-> decode_molecule(Basename,ArgList,Workspace,MolCode,0),
RestCode = ['(Trying to derive by inheritance) '|MolCode]
; CallType == (inheritance_candidate)
-> decode_molecule(Basename,ArgList,Workspace,MolCode,0),
RestCode = ['(Checking inheritance candidate) '|MolCode]
; CallType == (explicit_definition)
-> decode_molecule(Basename,ArgList,Workspace,MolCode,0),
RestCode = ['(Checking explicit definition for method) '|MolCode]
; CallType == (dynhead_before)
-> decode_molecule(Basename,ArgList,Workspace,MolCode,0),
RestCode = ['(Trying to derive via dynamic before-rules) '|MolCode]
; CallType == (dynhead_after)
-> decode_molecule(Basename,ArgList,Workspace,MolCode,0),
RestCode = ['(Trying to derive via dynamic after-rules) '|MolCode]
),
!.
%% The rest are classified as Prolog. These can be real prolog terms
%% or Flora primitives like insert{...}, throw{...}, etc.
%% Even if a call is a prolog call, its arguments can be Flora stuff, so
%% decode_literal_internal/3 processes them accordingly.
flora_decode_goal(Call,Code) :-
decode_literal_internal(Call,Code,0),
!.
%% Debugging
flora_decode_goal(Call,_) :-
flora_abort([Call,': flora_decode_goal/2 failed to decode']).
%%%%%%%%%%%%%%%%%%%% flora decode oid %%%%%%%%%%%%%%%%%%%%%%%
%% Call is an oid, although it may be a reified term.
flora_decode_oid(Call,Code) :-
decode_literal_internal(Call,Code,1).
%%%%%%%%%%%%%%%%%%%% flora_head %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_head(Head,HeadCode) :-
(is_list(Head)
-> decode_list_add_separator(Head,HeadCode,flora_decode_goal(_,_),', ')
; flora_decode_goal(Head,HeadCode)
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Decoding molecule %%%%%%%%%%%%%%%%%%%%%%%%%
%% Level=0: top level; Level=1: reified predicate/molecule argument of a functor
decode_molecule(Wrapper,ComponentList,Workspace,[ReifyStart,[MolCode|WCode],ReifyEnd],Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
(flora_match_substring(FLDEBUGPREFIX,Wrapper,forward,0,End),! ; End=0),
flora_get_substring(Wrapper,End,_,BaseWrapper),
decode_list_as_list(ComponentList,ComponentListCode,decode_literal_internal(_,_,1)),
decode_molecule_base(BaseWrapper,ComponentListCode,MolCode),
workspace_code(Workspace,WCode).
%% Wrapper, Args, Code
decode_molecule_base(WRAP_FD, [O,M,V], [O,'[',M,' -> ',V,']']).
decode_molecule_base(WRAP_FD, [O,M], [O,'[',M,' -> ','_',']']).
decode_molecule_base(WRAP_MVD, [O,M,V], [O,'[',M,' ->> ',V,']']).
decode_molecule_base(WRAP_MVD, [O,M], [O,'[',M,' ->> ','_',']']).
decode_molecule_base(WRAP_IFD, [O,M,V], [O,'[',M,' *-> ',V,']']).
decode_molecule_base(WRAP_IFD, [O,M], [O,'[',M,' *-> ','_',']']).
decode_molecule_base(WRAP_IMVD, [O,M,V], [O,'[',M,' *->> ',V,']']).
decode_molecule_base(WRAP_IMVD, [O,M], [O,'[',M,' *->> ','_',']']).
decode_molecule_base(WRAP_FDSIG, [O,M,V], [O,'[',M,' => ',V,']']).
decode_molecule_base(WRAP_IFDSIG, [O,M,V], [O,'[',M,' *=> ',V,']']).
decode_molecule_base(WRAP_MVDSIG, [O,M,V], [O,'[',M,' =>> ',V,']']).
decode_molecule_base(WRAP_IMVDSIG, [O,M,V], [O,'[',M,' *=>> ',V,']']).
decode_molecule_base(WRAP_MVDINC, [O,M,V], [O,'[',M,' +>> ',V,']']).
decode_molecule_base(WRAP_IMVDINC, [O,M,V], [O,'[',M,' *+>> ',V,']']).
decode_molecule_base(WRAP_MVDTOLIST, [O,M,V], [O,'[',M, ' ->-> ',V,']']).
decode_molecule_base(WRAP_IMVDTOLIST, [O,M,V], [O,'[',M, ' *->-> ',V,']']).
decode_molecule_base(WRAP_ISA, [O,C], [O,':',C]).
decode_molecule_base(WRAP_SUB, [Sub,Sup], [Sub,'::',Sup]).
%% boolean method
decode_molecule_base(WRAP_METH, [O,P], [O,'[',P,']']).
%% inheritable boolean method
decode_molecule_base(WRAP_IMETH, [O,P], [O,'[*',P,']']).
%% procedural boolean method
decode_molecule_base(WRAP_TRAN, [O,P], [O,'[#',P,']']).
decode_molecule_base(WRAP_OBJEQL, [O1,O2], [O1,' :=: ',O2]).
%%%%%%%%%%%%%%%%%%%%% Decode HiLog Call %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Level=0: top level; Level=1: reified predicate/molecule argument of a functor
decode_hilog_call(HiLogPred,Args,WS,[ReifyStart,Code,ReifyEnd],Level) :-
((Level==0; var(WS)) -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(HiLogPred,HiLogPredCode,1),
Code = [HiLogPredCode|RestCode1],
(Args == [], RestCode1 = RestCode2, !
;
decode_list_add_separator(Args,ArgCode1,decode_literal_internal(_,_,1),','),
RestCode1 = ['(',ArgCode1,')'|RestCode2]
),
(nonvar(WS)
-> workspace_code(WS,WSCode),
RestCode2 = WSCode
; RestCode2 = []
).
%%%%%%%%%%%%%%%%%%%%%% Decode Prolog Call %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% flora prolog-style builtin: declared as flora_prlg in flrprolog.P
decode_prolog_call([F,Args,Arity],Code) :-
flora_prlgdef(F,Arity),
!,
decode_builtin(F,Arity,Args,Code).
%% prolog call
decode_prolog_call([F,Args,_Arity],Code) :-
(Args == []
-> Code = [F,'@prolog()']
; decode_list_add_separator(Args,ArgsCode,decode_literal_internal(_,_,1),','),
Code = [F,'(',ArgsCode,')@prolog()']
).
decode_builtin(F,0,_,[F]) :- !.
%% This would have to be expanded to deal with unary ops
%% (i.e., print them as ope arg)
decode_builtin(F,1,[Arg],[F,'(',ArgCode,')']) :-
!,
decode_literal_internal(Arg,ArgCode,1).
%% This deals with binary ops
decode_builtin(F,2,[Arg1,Arg2],Code) :-
!,
decode_literal_internal(Arg1,Arg1Code,1),
decode_literal_internal(Arg2,Arg2Code,1),
((flora_opdef(_,xfx,F); flora_opdef(_,yfx,F); flora_opdef(_,xfy,F))
-> Code = [Arg1Code, ' ', F, ' ', Arg2Code]
; Code = [F,'(',Arg1Code,',',Arg2Code,')']
).
decode_builtin(F,_,Args,[F,'(',ArgsCode,')']) :-
decode_list_add_separator(Args,ArgsCode,decode_literal_internal(_,_,1),',').
%%%%%%%%%%%%%%%%%%%%%% IF %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_if_statement([Cond,Then],['IF (',CondCode,') THEN (',ThenCode,')']) :-
flora_decode_goal(Cond,CondCode),
flora_decode_goal(Then,ThenCode).
decode_if_statement([Cond,Then,Else],['IF (',CondCode,') THEN (',ThenCode,') ELSE (',ElseCode,')']) :-
flora_decode_goal(Cond,CondCode),
flora_decode_goal(Then,ThenCode),
flora_decode_goal(Else,ElseCode).
%%%%%%%%%%%%%%%%%%%%%% UNLESS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_unless(Cond,Action,['UNLESS (',CondCode,') DO (',ActionCode,')']) :-
flora_decode_goal(Cond,CondCode),
flora_decode_goal(Action,ActionCode).
%%%%%%%%%%%%%%%%%%%%%% WHILE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_while(LoopType,Cond,Action,['WHILE (',CondCode,') ',LoopType,' (',ActionCode,')']) :-
flora_decode_goal(Cond,CondCode),
flora_decode_goal(Action,ActionCode).
%%%%%%%%%%%%%%%%%%%%%% UNTIL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_until(LoopType,Action,Cond,[LoopType,' (',ActionCode,') UNTIL (',CondCode,')']) :-
flora_decode_goal(Action,ActionCode),
flora_decode_goal(Cond,CondCode).
%%%%%%%%%%%%%%%%%%%%% Updates %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
is_update_call(FLLIBINSERT, FL_INSERT).
is_update_call(FLLIBINSERTALL, FL_INSERTALL).
is_update_call(FLLIBBTINSERT, FL_BTINSERT).
is_update_call(FLLIBBTINSERTALL, FL_BTINSERTALL).
is_update_call(FLLIBDELETE, FL_DELETE).
is_update_call(FLLIBDELETEALL, FL_DELETEALL).
is_update_call(FLLIBBTDELETE, FL_BTDELETE).
is_update_call(FLLIBBTDELETEALL, FL_BTDELETEALL).
is_update_call(FLLIBERASE, FL_ERASE).
is_update_call(FLLIBERASEALL, FL_ERASEALL).
is_update_call(FLLIBBTERASE, FL_BTERASE).
is_update_call(FLLIBBTERASEALL, FL_BTERASEALL).
is_update_call(FLLIBINSERTRULE_A, FL_INSERTRULE_A).
is_update_call(FLLIBINSERTRULE_Z, FL_INSERTRULE_Z).
%% Level=0: top level; Level=1: reified predicate/molecule argument of a functor
decode_update(UpdName,
[UpdLiterals],
[ReifyStart,UpdName,'{',UpdLiteralsCode,'}',ReifyEnd],
Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_update_literals(UpdLiterals,UpdLiteralsCode).
decode_update(UpdName,
[UpdLiterals,Query],
[ReifyStart,UpdName,'{',UpdLiteralsCode,'| ',QueryCode,'}',ReifyEnd],
Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(Query,QueryCode,0),
decode_update_literals(UpdLiterals,UpdLiteralsCode).
%% decodes lists of update literals [FLSYSDBUPDATE(Lit,_Storage,_Module),...]
decode_update_literals([],[]) :- !.
decode_update_literals([FLSYSDBUPDATE(Lit,_Storage,_Module)|T],[LitCode,Comma|TCode]) :-
!,
decode_literal_internal(Lit,LitCode,0),
(T == [] -> Comma = '' ; Comma = ', '),
decode_update_literals(T,TCode).
decode_update_literals([FLSYSRULEUPDATE(Head,Body)|T],
[[HeadCode,' :- ', BodyCode],Comma|TCode]) :-
decode_head(Head,HeadCode),
decode_literal_internal(Body,BodyCode,0),
(T == [] -> Comma = '' ; Comma = ', '),
decode_update_literals(T,TCode).
%%%%%%%%%%%%%%%%%%%%% Aggregate Ops %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Level=0: top level; Level=1: reified predicate/molecule argument of a functor
decode_aggregate(AggName,AggVar,GrpVarList,Query,AggResult,
[ReifyStart,AggResultCode,' = ',AggName,
'{',AggVar,GrpVarListCode,'| ',QueryCode,'}',ReifyEnd],
Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(AggResult,AggResultCode,0),
(GrpVarList==[]
-> GrpVarListCode = ''
; decode_list_add_separator(GrpVarList,InterimCode,=(_,_),','),
GrpVarListCode = ['[',InterimCode,']']
),
decode_literal_internal(Query,QueryCode,0).
is_aggregate_call(FLLIBMIN,FL_MIN).
is_aggregate_call(FLLIBMAX,FL_MAX).
is_aggregate_call(FLLIBSUM,FL_SUM).
is_aggregate_call(FLLIBAVG,FL_AVG).
is_aggregate_call(FLLIBCOUNT,FL_COUNT).
is_aggregate_call(FLLIBCOLLECTSET,FL_COLLECTSET).
is_aggregate_call(FLLIBCOLLECTBAG,FL_COLLECTBAG).
%%%%%%%%%%%%%%%%%%%%% Flora built-in primitives foo{...} %%%%%%%%%%%%%%%%%
decode_primitive(BuiltinName,ArgsCode,
[ReifyStart,BuiltinName,'{',ArgsCode,'}',ReifyEnd],
Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}').
%%%%%%%%%%%%%%%%%%%%%%%%%% Decode list as commalist %%%%%%%%%%%%%%%%%%
%% Takes a list, applies transformation ConversionCall(In,Out) %%
%% and produces a list of the results separated by a separator %%
%% The last arg specifies the separator between list items %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_list_add_separator([],[],_,_) :- !.
decode_list_add_separator([L],[CodeL],ConversionCall,_Separator) :-
!,
arg(1,ConversionCall,L),
call(ConversionCall),
arg(2,ConversionCall,CodeL).
decode_list_add_separator([L|R],[CodeL,Separator|CodeR],ConversionCall,Separator) :-
copy_term(ConversionCall,ConversionCall1),
arg(1,ConversionCall,L),
call(ConversionCall),
arg(2,ConversionCall,CodeL),
decode_list_add_separator(R,CodeR,ConversionCall1,Separator).
%%%%%%%%%%%%%%%%%%%%%%%%%% decode list of goals as list %%%%%%%%%%%%%%%
%% Takes a list, applies transformation ConversionCall(In,Out) %%
%% to each member and produces a list of the results %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_list_as_list([],[],_) :- !.
decode_list_as_list([G|GoalList],[GCode|GoalCodeList],ConversionCall) :-
copy_term(ConversionCall,ConversionCall1),
arg(1,ConversionCall,G),
call(ConversionCall),
arg(2,ConversionCall,GCode),
decode_list_as_list(GoalList,GoalCodeList,ConversionCall1).
/*
%%%%%%%%%%%%%%%%%%%%%%%%%% Decode commalist as commalist %%%%%%%%%%%%%
%% Takes a commalist (G1,G2,G3,...), applies transformation %%
%% ConversionCall(In,Out) and produces a list of the results %%
%% by a separator given in the last argument %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
decode_commalist_add_separator((G1,G2),[CodeG1,Separator|CodeG2],ConversionCall,Separator) :-
!,
copy_term(ConversionCall,ConversionCall1),
arg(1,ConversionCall,G1),
call(ConversionCall),
arg(2,ConversionCall,CodeG1),
(var(G2) -> G2=CodeG2
; decode_commalist_add_separator(G2,CodeG2,ConversionCall1,Separator)
).
decode_commalist_add_separator(G,CodeG,ConversionCall,_Separator) :-
!,
arg(1,ConversionCall,G),
call(ConversionCall),
arg(2,ConversionCall,CodeG).
*/
%%%%%%%%%%%%%%%%%%%%%%%%%%% workspace_code %%%%%%%%%%%%%%%%%%%%%%%%%%%%
workspace_code(WS,WSCode) :-
(WS==main
-> WSCode = []
; WSCode = ['@',WS]
).
%%%%%%%%%%%%%%%%%%%%%%%%%%% Decode anonymous OID %%%%%%%%%%%%%%%%%%%%%%
decode_anon_oid(NewOid,Code) :-
atom(NewOid),
flora_match_substring(FL_NEWOID_PREFIX,NewOid,forward,0,Pos),
flora_get_substring(NewOid,Pos,_,Suffix),
Code = ['_#''',Suffix].
%%%%%%%%%%%%%%%%%%%%%% Classifier %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
classify_call(Call, Type,Basename,ArgList,Workspace) :-
flora_decode_predicate(Call,Type1,Workspace,Prefix,Basename1,ArgList1),
%% The following is a debugging statement.
%% Helps weed out calls that should be suppressed by the debugger
/*
writeln(('Decodecall: ',Call,Type1,Workspace,Prefix,Basename1,ArgList,ArgList1)),
*/
(Type1 == (flora)
-> (Prefix==inheritance_
-> Basename = Basename1, Type = (inheritance), ArgList = ArgList1
; (Prefix==candidate_class_ ; Prefix==candidate_object_)
-> Basename = Basename1, Type = (inheritance_candidate), ArgList = ArgList1
; Prefix==local_
-> Basename = Basename1, Type = (explicit_definition), ArgList = ArgList1
; Prefix==dyna_ % This is actually hidden (possible future use)
-> Basename = Basename1, Type = (dynhead_before), ArgList = ArgList1
; Prefix==dynz_ % This is actually hidden (possible future use)
-> Basename = Basename1, Type = (dynhead_after), ArgList = ArgList1
; %% must be a hilog predicate derivative formed by specialization
%% such as FLORA_PREFIX'usermod''main''flapply_#303'
flora_concat_atoms([WRAP_HILOG,'_'],Prefix)
-> Type = (hilog), ArgList1 = [Basename | ArgList]
; Type = Type1, Basename = Basename1, ArgList = ArgList1
)
; Type1 == (prolog), Basename1 = flora_db_find_base,
Call = flora_db_find_base(Trie,RealCall),
flora_match_substring(FLORA_PREFIX,Trie,forward,0,_)
-> %% Checking against base facts
flora_decode_predicate(RealCall,RealType,Workspace,_,Basename,ArgList),
Type = (basefact,RealType)
%% Hilog term that is not a hilog predicate
; Type1 == (prolog), Basename1 = WRAP_HILOG
-> Type = (hilog), ArgList1 = [Basename | ArgList]
; Type = Type1, Basename = Basename1, ArgList = ArgList1
).
%%%%%%%%%%%%%%%%%%%%% internal decode goal util %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Level=0: top level; Level=1: reified predicate/molecule argument of a functor
decode_literal_internal(Call,Code,_Level) :-
(atomic(Call);var(Call)),
!,
(atom(Call), flora_decode_predicate(Call,_,WS,_,Basename,_),
nonvar(WS), nonvar(Basename)
-> workspace_code(WS,WSCode),
Code = [Basename|WSCode]
; decode_anon_oid(Call,OidCode)
-> Code = OidCode
; Code = [Call]
).
decode_literal_internal((NameOrVar = Var),[NameOrVar,' = ',Var],_Level) :-
var(Var),
(var(NameOrVar); atom(NameOrVar)),
!.
%% This occurs when you have hilog-lit@Module, where Module is a var
decode_literal_internal(FLLIBMODLIT(WRAP_HILOG,Args,Module),Code,Level) :-
!,
%% Don't increment nesting level
(nonvar(Args), !
; flora_abort('FLLIBMODLIT(WRAP_HILOG,Args,Module): Internal error: Invalid goal in decode_literal_internal/3')
),
Args = [Basename|ArgList],
decode_hilog_call(Basename,ArgList,Module,Code,Level).
%% This occurs when you have X@..., i.e., the literal part is a variable
decode_literal_internal(FLLIBMODLIT(FL_LIBMOD,Args,Module),
[ReifyStart,ArgCode,'@',Module,ReifyEnd],
Level) :-
!,
%% Don't increment nesting level
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
((var(Args) ; atomic(Args)) -> ArgCode = Args
; decode_literal_internal(Args,ArgCode,Level)
).
%% This occurs when you have flogic-lit@Module, where Module is a var
decode_literal_internal(FLLIBMODLIT(Basename,Args,Module),Code,Level) :-
!,
%% Don't increment nesting level
decode_molecule(Basename,Args,Module,Code,Level).
decode_literal_internal(FLLIBREFRESH(GoalList),Code,Level) :-
!,
decode_list_add_separator(GoalList,GLCode,decode_literal_internal(_,_,0),', '),
decode_primitive(FL_REFRESH,GLCode,Code,Level).
decode_literal_internal(FLLIBCATCH(Call,Catcher,Handler),Code,Level) :-
decode_literal_internal(Call,CallCode,0),
decode_literal_internal(Catcher,CatcherCode,0),
decode_literal_internal(Handler,HandlerCode,0),
decode_primitive(FL_CATCH,[CallCode,',',CatcherCode,',',HandlerCode],Code,Level).
decode_literal_internal(FLLIBTHROW(Catcher),Code,Level) :-
decode_literal_internal(Catcher,CatcherCode,0),
decode_primitive(FL_THROW,CatcherCode,Code,Level).
decode_literal_internal(P2H_PREDICATE(Prolog,Hilog,_,_),Code,Level) :-
decode_literal_internal(Prolog,PrologCode,0),
decode_literal_internal(Hilog,HilogCode,0),
decode_primitive(FL_P2H,[PrologCode,',',HilogCode],Code,Level).
decode_literal_internal(FLLIBIFTHENELSE(Cond,Then,Else),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_if_statement([Cond,Then,Else],Code).
decode_literal_internal(FLLIBIFTHEN(Cond,Then),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_if_statement([Cond,Then],Code).
decode_literal_internal(FLLIBUNLESSDO(Cond,Action),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_unless(Cond,Action,Code).
decode_literal_internal(FLLIBWHILEDO(Cond,Action),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_while('DO',Cond,Action,Code).
decode_literal_internal(FLLIBWHILELOOP(Cond,Action),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_while('LOOP',Cond,Action,Code).
decode_literal_internal(FLLIBDOUNTIL(Action,Cond),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_until('DO',Action,Cond,Code).
decode_literal_internal(FLLIBLOOPUNTIL(Action,Cond),[ReifyStart,Code,ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_until('LOOP',Action,Cond,Code).
%% flLoad in the form of [...]
decode_literal_internal(FLLIBLOAD(Arg),[ReifyStart,'[',LoadCode,']',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
(Arg = '>>'(File,Module)
-> LoadCode = [File,'>>',Module]
; LoadCode = File
).
decode_literal_internal(FLLIBUNIVEQFORM(Left,Right),
[ReifyStart,LeftCode,' ',FL_UNIVEQFORM,' ',RightCode,ReifyEnd],
Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(Left,LeftCode,0),
decode_literal_internal(Right,RightCode,0).
decode_literal_internal(WRAP_FDSKOLEM(X,Y),[XCode,'.',YCode],_Level) :-
!,
decode_literal_internal(X,XCode,0),
decode_literal_internal(Y,YCode,0).
decode_literal_internal(WRAP_IFDSKOLEM(X,Y),[XCode,'!',YCode],_Level) :-
!,
decode_literal_internal(X,XCode,0),
decode_literal_internal(Y,YCode,0).
%% Call prolog predicate in a different module; must be before commalist
%% We loose the module name in decoding
decode_literal_internal((X =.. _List, call(X)),
[ReifyStart,'call(',Code,')',ReifyEnd],
Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(X,Code,0).
%% Aggregates should be handled before commalists
decode_literal_internal((Call, AggResultVar=InterimResultVar),Code,Level) :-
Call =.. [AggLib,AggVar,GrpVarList,Query,InterimResultVar],
is_aggregate_call(AggLib,AggName),
!,
decode_aggregate(AggName,AggVar,GrpVarList,Query,AggResultVar,Code,Level).
%% commalist
decode_literal_internal((L,R),[ReifyStart,'(',[LCode,', '|RCode],')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(L,LCode,0),
decode_literal_internal(R,RCode,0).
%% list
decode_literal_internal(Call,['"', Code, '"'],_Level) :-
is_charlist(Call),
!,
atom_codes(Code,Call).
decode_literal_internal('.'(H,T),['[',Code,']'],Level) :-
!,
decode_list_add_separator('.'(H,T),Code,decode_literal_internal(_,_,Level),', ').
decode_literal_internal(';'(L,R),[ReifyStart,'(',LCode,'; ',RCode,')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(L,LCode,0),
decode_literal_internal(R,RCode,0).
%% Can this happen?
decode_literal_internal('->'(Call1,Call2),[ReifyStart,Call1Code,' -> ',Call2Code,ReifyEnd],Level) :-
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
decode_literal_internal(Call1,Call1Code,0),
decode_literal_internal(Call2,Call2Code,0).
%% call(...), tnot(...), not(...), \+ (...)
decode_literal_internal(FLORA_TNOT_PREDICATE(Subcall),[ReifyStart,'(','tnot ',SubcallCode,')'],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
flora_decode_goal(Subcall,SubcallCode).
decode_literal_internal(tnot(Subcall),[ReifyStart,'(tnot ',SubcallCode,')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
flora_decode_goal(Subcall,SubcallCode).
decode_literal_internal(not(Subcall),[ReifyStart,'(\+ ',SubcallCode,')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
flora_decode_goal(Subcall,SubcallCode).
decode_literal_internal('\+'(Subcall),[ReifyStart,'(\+ ',SubcallCode,')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
flora_decode_goal(Subcall,SubcallCode).
decode_literal_internal(call(Subcall),[ReifyStart,'call(',SubcallCode,')',ReifyEnd],Level) :-
!,
(Level==0 -> ReifyStart='',ReifyEnd='' ; ReifyStart='${',ReifyEnd='}'),
flora_decode_goal(Subcall,SubcallCode).
%% An update
decode_literal_internal(Call,Code,Level) :-
Call =.. [UpdPred,UpdLiterals|Query],
is_update_call(UpdPred,UpdName),
!,
(Query==[]
-> decode_update(UpdName,[UpdLiterals],Code,Level)
; Query = [RealQuery],
decode_update(UpdName,[UpdLiterals,RealQuery],Code,Level)
).
decode_literal_internal(Call,Code,Level) :-
(\+callable(Call)
-> flora_abort([Call,': Ill-formed HiLog term in decode_literal_internal/3'])
;
classify_call(Call,Type,BasenameOrPred,Args,WS),
(Type == (hilog)
-> decode_hilog_call(BasenameOrPred,Args,WS,Code,Level)
; Type == (prolog)
-> functor(Call,Functor,Arity),
decode_prolog_call([Functor,Args,Arity],Code)
; Type == (flogic)
-> decode_molecule(BasenameOrPred,Args,WS,Code,Level)
; % cannot decode
flora_abort([Call,': decode_literal_internal/3 failed to decode'])
)
).
/*
%% Keep for now in case we decide to be sophisticated and print true var names
%% Extracts and writes variables from the list [=(name,internalVar), ...]
%% or from the list [internalVar, internalVar, ...]
flora_write_vars(V) :- V== [], !.
flora_write_vars([V|Rest]) :-
var(V), !, flora_write_vars(V,Rest).
flora_write_vars([=(_N,V)|Rest]) :-
!, flora_write_vars(V,Rest).
flora_write_vars(V,Rest) :-
write(V),
(Rest == [] -> true
; write(','), flora_write_vars(Rest)
).
*/
syntax highlighted by Code2HTML, v. 0.9.1