/* 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) ). */