1% ===================================================================
    2% File 'logicmoo_util_ctx_frame.pl'
    3% Purpose: An Implementation in SWI-Prolog of Unwindable context frames
    4% Maintainer: Douglas Miles
    5% Contact: $Author: dmiles $@users.sourceforge.net ;
    6% Version: 'logicmoo_util_ctx_frame.pl' 1.0.0
    7% Revision:  $Revision: 1.1 $
    8% Revised At:   $Date: 2002/07/11 21:57:28 $
    9% ===================================================================
   10% ===================================================================
   11%  LocalContexts
   12%   They hold name-values in
   13%     -- assoc/1 lists
   14%     -- open tailed lists
   15%     -- frame/1 contains one or more of the above
   16
   17% v/3s 
   18%  = v(Value,Setter,KeyDestructor)
   19
   20% frame/3s
   21%  = frame(Named,Destructor,Ctx)
   22
   23% well i played with a couple few differnt environment impls.. they have their pros cons.. one impl.. 
   24% that was unique is that an array of "binding pairs" live in an arraylist.. to be "in" an environment 
   25% it meant that you held an "index" into the arry list that as you went backwards you'd find your bindings.. each symbol had a java ftInt field "lastBindingIndex" 
   26% .. that was a "hint" to where you could fastforward the backwards search .. end named binding context also had a "index" to when you leave a named block.. 
   27% you could quickly reset the top of an index.
   28% File: /opt/PrologMUD/pack/logicmoo_base/prolog/logicmoo/util/logicmoo_util_ctx_frame.pl
   29:- module(logicmoo_util_ctx_frame,
   30          [ addCtxValue/3,
   31            addCtxValue1/3,
   32            addKeyValue/2,
   33            appendAttributes/4,
   34            bestSetterFn/3,
   35            checkCtx/1,
   36            copy_term_numvars/2,
   37            currentContext/2,
   38            delete_safe/3,
   39            eqmember/2,
   40            evil_term/3,
   41            getCtxValue/3,
   42            getKeyValue/2,
   43            get_ctx_frame_holder/3,
   44            get_ctx_frame_holder1/3,
   45            get_ctx_holder/2,
   46            get_ctx_holder1/2,
   47            get_ctx_holderFreeSpot/3,
   48            get_ctx_holderFreeSpot0/3,
   49            get_ctx_holderFreeSpot1/3,
   50            get_ctx_holderFreeSpot1/5,
   51            get_ctx_value/4,
   52            get_n_value/6,
   53            get_o_value/4,
   54            get_o_value0/4,
   55            get_o_value1/4,
   56            hideIfNeeded/2,
   57            lastMemberCtx/2,
   58            lastMemberCtx/3,
   59            makeLocalContext/2,
   60            makeLocalContext1/2,
   61            mergeAppend0/3,
   62            no_cyclic_terms/0,
   63            popCtxFrame/3,
   64            pushCtxFrame/3,
   65            remCtxValue/3,
   66            revappend_0/3,
   67            reverseA/2,
   68            setCtxValue/3,
   69            to_open_list/4,
   70            unwrapValue/2,
   71            unwrapValue1/2
   72          ]).   73:- module_transparent
   74        addCtxValue/3,
   75        addCtxValue1/3,
   76        addKeyValue/2,
   77        appendAttributes/4,
   78        bestSetterFn/3,
   79        checkCtx/1,
   80        copy_term_numvars/2,
   81        currentContext/2,
   82        delete_safe/3,
   83        eqmember/2,
   84        getCtxValue/3,
   85        getKeyValue/2,
   86        get_ctx_frame_holder/3,
   87        get_ctx_frame_holder1/3,
   88        get_ctx_holder/2,
   89        get_ctx_holder1/2,
   90        get_ctx_holderFreeSpot/3,
   91        get_ctx_holderFreeSpot0/3,
   92        get_ctx_holderFreeSpot1/3,
   93        get_ctx_holderFreeSpot1/5,
   94        get_ctx_value/4,
   95        get_n_value/6,
   96        get_o_value/4,
   97        get_o_value0/4,
   98        get_o_value1/4,
   99        hideIfNeeded/2,
  100        lastMemberCtx/2,
  101        lastMemberCtx/3,
  102        makeLocalContext/2,
  103        makeLocalContext1/2,
  104        mergeAppend0/3,
  105        no_cyclic_terms/0,
  106        popCtxFrame/3,
  107        pushCtxFrame/3,
  108        remCtxValue/3,
  109        revappend_0/3,
  110        reverseA/2,
  111        setCtxValue/3,
  112        to_open_list/4,
  113        unwrapValue/2,
  114        unwrapValue1/2.  115:- dynamic
  116        no_cyclic_terms/0.  117
  118
  119
  120
  121:- if(current_predicate(lmcode:combine_logicmoo_utils/0)).  122:- module(ctx_frame,[
  123         lastMemberCtx/2,
  124         lastMemberCtx/3,
  125         pushCtxFrame/3,
  126         getCtxValue/3,
  127         makeLocalContext/2,
  128         appendAttributes/4,
  129         currentContext/2]).  130
  131:- else.  132
  133:- endif.  134
  135
  136
  137% :- ensure_loaded((logicmoo_util_library)).
  138% :-ensure_loaded((logicmoo_util_bugger)).
  139
  140
  141%= 	 	 
 currentContext(?Name, ?X) is semidet
Current Context.
  147currentContext(Name,X):-quietly(makeLocalContext(Name,X)),!.
  148
  149
  150% ===================================================================
  151:- dynamic(no_cyclic_terms).  152
  153
  154%= 	 	 
 no_cyclic_terms is semidet
No Cyclic Terms.
  160no_cyclic_terms.
  161
  162
  163%= 	 	 
 makeLocalContext(?Name, ?Ctx) is semidet
Make Local Context.
  169makeLocalContext(Name,Ctx):-makeLocalContext1(Name,Ctx),!,setCtxValue(ctx,Ctx,Name),!.
  170
  171
  172%= 	 	 
 makeLocalContext1(?Gensym_Key, :TermGensym_Key) is semidet
Make Local Context Secondary Helper.
  178makeLocalContext1(Gensym_Key, [frame(Gensym_Key,no_destructor,[assoc(AL)|_])|_]):-    
  179   list_to_assoc([
  180    a-v(is_a,set_assoc,no_destructor(a)),
  181    a-v(is_a2,set_assoc,no_destructor(a)),
  182    b-v(is_b,set_assoc,no_destructor(b))],AL).
  183
  184
  185
  186%= 	 	 
 unwrapValue(?HValue, ?TValue) is semidet
Unwrap Value.
  192unwrapValue(HValue,TValue):-TValue==deleted,!,not(unwrapValue1(HValue,_)),!.
  193unwrapValue(HValue,TValue):-unwrapValue1(HValue,Value),!,TValue=Value.
  194
  195
  196%= 	 	 
 unwrapValue1(?Value, ?Value) is semidet
Unwrap Value Secondary Helper.
  202unwrapValue1(v(ValueHolder,_SetterFun,_KeyDestroyer),Value):-!,unwrapValue1(ValueHolder,Value).
  203unwrapValue1(deleted,_):-!,fail.
  204unwrapValue1(Value,Value):-!.
  205
  206
  207%= 	 	 
 bestSetterFn(?Value, ?OuterSetter, ?OuterSetter) is semidet
Best Setter Function.
  213bestSetterFn(v(_,Setter,_),_OuterSetter,Setter):-!.
  214bestSetterFn(_Value,OuterSetter,OuterSetter).
  215
  216
  217%= 	 	 
 getCtxValue(?Name, ?Ctx, ?Value) is semidet
Get Context Value.
  223getCtxValue(Name,Ctx,Value):-checkCtx(Ctx), quietly(( get_ctx_holder(Ctx,Holder),get_o_value(Name,Holder,HValue,_Setter),!, unwrapValue(HValue,Value))),!.
  224getCtxValue(Name,CtxI,Value):-checkCtx(CtxI),lastMemberCtx(Ctx,CtxI),quietly(( get_ctx_holder(Ctx,Holder),get_o_value(Name,Holder,HValue,_Setter),!, unwrapValue(HValue,Value))),!.
  225
  226
  227%= 	 	 
 setCtxValue(?Name, ?Ctx, ?Value) is semidet
Set Context Value.
  233setCtxValue(Name,Ctx,Value):-checkCtx(Ctx),get_ctx_holder(Ctx,Holder),get_o_value(Name,Holder,HValue,Setter),unwrapValue(HValue,CurrentValue),!,(CurrentValue=Value;call(Setter,Value)),!.
  234setCtxValue(Name,Ctx,Value):-checkCtx(Ctx),addCtxValue1(Name,Ctx,Value),!.
  235
  236
  237%= 	 	 
 addCtxValue(?Name, ?Ctx, ?Value) is semidet
Add Context Value.
  243addCtxValue(Name,Ctx,Value):-checkCtx(Ctx),addCtxValue1(Name,Ctx,Value),!.
  244
  245%= 	 	 
 addCtxValue1(?Name, ?Ctx, ?Value) is semidet
Add Context Value Secondary Helper.
  251addCtxValue1(Name,Ctx,Value):-get_ctx_holderFreeSpot(Ctx,Name=v(Value,Setter,Destructor),Destructor),!,ignore(Setter=no_setter(Name)).
  252
  253
  254%= 	 	 
 remCtxValue(?Name, ?Ctx, ?Value) is semidet
Remove/erase Context Value.
  260remCtxValue(Name,Ctx,_Value):-checkCtx(Ctx),setCtxValue(Name,Ctx,deleted),!.
  261
  262
  263
  264%= 	 	 
 pushCtxFrame(?Name, ?Ctx, ?NewValues) is semidet
Push Context Frame.
  270pushCtxFrame(Name,Ctx,NewValues):-checkCtx(Ctx),get_ctx_holderFreeSpot(Ctx,Holder,GuestDest),!,Holder=frame(Name,GuestDest,NewValues).
  271
  272
  273%= 	 	 
 popCtxFrame(?Name, ?Ctx, ?PrevValues) is semidet
Pop Context Frame.
  279popCtxFrame(Name,Ctx,PrevValues):-checkCtx(Ctx),get_ctx_frame_holder(Ctx,Name,Frame),Frame = frame(Name,Destructor,PrevValues),Destructor,!.
  280
  281
  282%= 	 	 
 checkCtx(?Ctx) is semidet
Check Context.
  288checkCtx(Ctx):-nonvar(Ctx),!.
  289checkCtx(Ctx):-makeLocalContext(broken,Ctx),!.
  290
  291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  292%%% get the frame holder
  293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  294
  295%= 	 	 
 get_ctx_frame_holder(?Ctx, ?Name, ?R) is semidet
Get Context Frame Holder.
  301get_ctx_frame_holder(Ctx,Name,R):-compound(Ctx),get_ctx_frame_holder1(Ctx,Name,R).
  302
  303%= 	 	 
 get_ctx_frame_holder1(:TermARG1, ?Name, ?R) is semidet
Get Context Frame Holder Secondary Helper.
  309get_ctx_frame_holder1(v(_,_,_),_Name,_R):-!,fail.
  310get_ctx_frame_holder1(frame(Name,Dest,Ctx),Name,R):- R = frame(Name,Dest,Ctx),!.
  311get_ctx_frame_holder1([H|T],Name,R):- nonvar(H), !, ( get_ctx_frame_holder(T,Name,R);get_ctx_frame_holder1(H,Name,R)) .
  312%%get_ctx_frame_holder1(Ctx,Name,Ctx):-!,get_ctx_frame_holder1(Ctx,Name,R).
  313
  314
  315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  316%%% get the holders areas last in first out %%%%%
  317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  318%%% get_ctx_holder(+Ctx, -PlaceToSearch),
  319
  320
  321%= 	 	 
 get_ctx_holder(?Ctx, ?R) is semidet
Get Context Holder.
  327get_ctx_holder(Ctx,R):-compound(Ctx),get_ctx_holder1(Ctx,R).
  328
  329%= 	 	 
 get_ctx_holder1(?Ctx, ?Ctx) is semidet
Get Context Holder Secondary Helper.
  335get_ctx_holder1([H|T],R):- nonvar(H), !, ( get_ctx_holder(T,R);get_ctx_holder1(H,R)) .
  336get_ctx_holder1(v(_,_,_),_R):-!,fail.% get_ctx_holder(Ctx,R).
  337get_ctx_holder1(frame(_N,_Dest,Ctx),R):-!,get_ctx_holder(Ctx,R).
  338%get_ctx_holder1(Ctx,R):- functor(Ctx,F,A),A<3,!,fail.
  339get_ctx_holder1(assoc(Ctx),assoc(Ctx)):-!.
  340get_ctx_holder1(Ctx,Ctx).
  341
  342
  343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  344%%% find a free area to place a: vv(name,val) %%%%%
  345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  346%%% get_ctx_holderFreeSpot(+Ctx, -Put_NV, -CallToRemoveNV)
  347
  348
  349%= 	 	 
 get_ctx_holderFreeSpot(?Ctx, ?NamedValue, ?Destruct) is semidet
Get Context Holder Free Spot.
  355get_ctx_holderFreeSpot(Ctx,NamedValue,no_destructor(holder)):-no_cyclic_terms,!,get_ctx_holderFreeSpot0(Ctx,NamedValue,_NO_Destruct),!.
  356get_ctx_holderFreeSpot(Ctx,NamedValue,Destruct):-get_ctx_holderFreeSpot0(Ctx,NamedValue,Destruct).
  357
  358
  359%= 	 	 
 get_ctx_holderFreeSpot0(?Ctx, ?NamedValue, ?Destruct) is semidet
Get Context Holder Free Spot Primary Helper.
  365get_ctx_holderFreeSpot0(Ctx,NamedValue,Destruct):-compound(Ctx),get_ctx_holderFreeSpot1(Ctx,NamedValue,Destruct).
  366
  367
  368%= 	 	 
 get_ctx_holderFreeSpot1(:TermCtx, ?NamedValue, ?Destruct) is semidet
Get Context Holder Free Spot Secondary Helper.
  374get_ctx_holderFreeSpot1(assoc(_Ctx),_,_):-!,fail.
  375get_ctx_holderFreeSpot1(frame(Key,_Inner_Dest,Ctx),NamedValue,Destruct):- nonvar(Key), !, get_ctx_holderFreeSpot1(Ctx,NamedValue,Destruct).
  376get_ctx_holderFreeSpot1(Ctx,NamedValue,Destruct):-functor(Ctx,F,A),!,get_ctx_holderFreeSpot1(Ctx,F,A,NamedValue,Destruct).
  377
  378
  379%= 	 	 
 get_ctx_holderFreeSpot1(?Ctx, ?VALUE2, :PRED2VALUE3, ?NamedValue, ?Ctx) is semidet
Get Context Holder Free Spot Secondary Helper.
  385get_ctx_holderFreeSpot1(Ctx,'.',2,NamedValue,nb_setarg(Ctx,2,NEXT)):-arg(2,Ctx,Try1), var(Try1),!, Try1 = [NamedValue|NEXT].
  386get_ctx_holderFreeSpot1(Ctx,'.',2,NamedValue,Destruct):-arg(2,Ctx,Try2),get_ctx_holderFreeSpot0(Try2,NamedValue,Destruct).
  387
  388%%get_ctx_holderFreeSpot1(Ctx,_,_,NamedValue,_):-!,fail.
  389%%get_ctx_holderFreeSpot1(Ctx,_,_,NamedValue,nb_setarg(Ctx,N,NEXT)):-arg(N,Ctx,Try3),var(Try3),!, Try3 = [NamedValue|NEXT].
  390%%get_ctx_holderFreeSpot1(Ctx,_,_,NamedValue,Destruct):-arg(N,Ctx,Try4),get_ctx_holderFreeSpot0(Try4,NamedValue,Destruct).
  391
  392
  393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  394%%% find the value holder associated with a keyname
  395%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  396
  397%= 	 	 
 get_ctx_value(?Name, ?Ctx, ?Value, ?Setter) is semidet
Get Context Value.
  403get_ctx_value(Name,Ctx,Value,Setter):-nonvar(Name),var(Value),get_o_value(Name,Ctx,Value,OuterSetter),bestSetterFn(Value,OuterSetter,Setter).
  404
  405
  406%= 	 	 
 get_o_value(?Name, ?Ctx, ?Value, ?Setter) is semidet
Get Output Value.
  412get_o_value(Name,Ctx,Value,no_setter(Name)):-no_cyclic_terms,!,get_o_value0(Name,Ctx,Value,_HIDE_Setter),!.
  413get_o_value(Name,Ctx,Value,Setter):-quietly(get_o_value0(Name,Ctx,Value,Setter)),!.
  414
  415
  416%= 	 	 
 get_o_value0(?Name, ?Ctx, ?Value, ?Setter) is semidet
Get Output Value Primary Helper.
  422get_o_value0(Name,Ctx,Value,Setter):-compound(Ctx),get_o_value1(Name,Ctx,Value,Setter).
  423
  424%= 	 	 
 get_o_value1(?Name, :TermPred, ?Value, ?Setter) is semidet
Get Output Value Secondary Helper.
  430get_o_value1(Name,assoc(Ctx),Value,set_assoc):- get_assoc(Name,Ctx,Value),!.
  431get_o_value1(Name,frame(Key,_Inner_Dest,Ctx),Value,Setter):- nonvar(Key), get_o_value0(Name,Ctx,Value,Setter),!.
  432get_o_value1(Name,[H|T],Value,Setter):- !,(get_o_value0(Name,T,Value,Setter);get_o_value1(Name,H,Value,Setter)).
  433get_o_value1(Name,Pred,Value,Setter):-functor(Pred,F,A),!,get_n_value(Name,Pred,F,A,Value,Setter).
  434
  435
  436%= 	 	 
 get_n_value(?Name, ?Name, ?F, :PRED2A, ?Value, ?VALUE6) is semidet
Get N Value.
  442get_n_value(Name,Name,_F,_A,_Value,_):-!,fail.
  443get_n_value(Name,Pred,Name,1,Value,nb_setarg(1,Pred)):-arg(1,Pred,Value).
  444get_n_value(Name,Pred,Name,_,Value,Setter):- arg(1,Pred,Value),!,arg(2,Pred,Setter). % value can actually be 'Pred'
  445get_n_value(Name,Pred,Dash,2,Value,nb_setarg(2,Pred)):-arg(1,Pred,Name),member(Dash,[=,-,vv]),!, arg(2,Pred,Value).
  446%%get_n_value(Name,Pred,'.',2,Value,Setter):-arg(2,Pred,Try1), get_o_value0(Name,Try1,Value,Setter);(arg(1,Pred,Try2),get_o_value0(Name,Try2,Value,Setter)).
  447%%get_n_value(Name,Pred,_,_,Value,Setter):- !, arg(_,Pred,Try2),get_o_value0(Name,Try2,Value,Setter).
  448
  449
  450
  451%= 	 	 
 lastMemberCtx(?E, :TermList) is semidet
Last Member Context.
  457lastMemberCtx(_E,List):-var(List),!,fail.
  458lastMemberCtx(E,[H|List]):-lastMemberCtx(E,List);E=H.
  459
  460
  461%= 	 	 
 lastMemberCtx(?E, ?List, ?Rest) is semidet
Last Member Context.
  467lastMemberCtx(E,List,Rest):-lastMemberCtx(E,List),!,delete_safe(List,E,Rest),!.
  468
  469
  470%= 	 	 
 delete_safe(:TermList, ?E, :TermRest) is semidet
Delete Safely Paying Attention To Corner Cases.
  476delete_safe(List,_E,Rest):-var(List),!,Rest=List.
  477delete_safe(List,E,Rest):-is_list(List),!,delete(List,E,Rest).
  478delete_safe([H|List],E,Rest):- H==E,!,delete_safe(List,E,Rest).
  479delete_safe([H|List],E,[H|Rest]):-delete_safe(List,E,Rest).
  480
  481
  482
  483%= 	 	 
 getKeyValue(?FullList, :TermN) is semidet
Get Key Value.
  489getKeyValue(FullList,N=V):-lastMemberCtx(N=V,FullList),!.
  490%%addKeyValue(FullList,N=V):-nonvar(N),!,append(_Closed,[N=V|_],FullList),!.
  491
  492%= 	 	 
 addKeyValue(?FullList, ?NV) is semidet
Add Key Value.
  498addKeyValue(FullList,NV):- must((not(ground(FullList)),nonvar(NV))),append(_Closed,[NV|_],FullList),!.
  499
  500
  501% lastMember2(E,List):-to_open_list(_,Closed,_Open,List),reverse(Closed,Rev),member(E,Rev).
  502
  503%lastMemberCtx(End,List) :- append(_,[End|_],List).
  504
  505:- multifile evil_term/3.  506:- dynamic evil_term/3.  507
  508%= 	 	 
 evil_term(?Ctx, ?Before, ?After) is semidet
Evil Term.
  514evil_term(_Ctx,Before,After):-hideIfNeeded(Before,After),!.
  515
  516
  517%= 	 	 
 hideIfNeeded(?I, ?I) is semidet
Hide If Needed.
  523hideIfNeeded(I,I):- (var(I);atomic(I)),!.
  524hideIfNeeded([I|_],ctx):-nonvar(I),I=frame(_,_,_),!.
  525hideIfNeeded([I|_],ctx):-nonvar(I),functor(I,frame,_),!.
  526hideIfNeeded([I|N],[I0|N0]):-!,hideIfNeeded(I,I0),hideIfNeeded(N,N0),!.
  527hideIfNeeded(Comp,Comp2):-compound(Comp),Comp=..[L,I|ST],hideIfNeeded([I|ST],[OI|OIST]),Comp2=..[L,OI|OIST],!.
  528hideIfNeeded(I,I):-!.
  529
  530
  531
  532%= 	 	 
 to_open_list(?FullList, ?Closed, ?Open, ?FullList) is semidet
Converted To Open List.
  538to_open_list(FullList,Closed,Open,FullList) :- append(Closed,Open,FullList),var(Open),!.
  539to_open_list(Closed,Closed,Open,FullList) :- append(Closed,Open,FullList),!.
  540
  541
  542
  543%= 	 	 
 revappend_0(:TermARG1, ?Ys, ?Ys) is semidet
revappend Primary Helper.
  549revappend_0([], Ys, Ys).
  550revappend_0([X|Xs], Ys, Zs) :- revappend_0(Xs, [X|Ys], Zs).
  551
  552
  553%= 	 	 
 reverseA(?Xs, ?Ys) is semidet
Reverse A.
  559reverseA(Xs,Ys) :- revappend_0(Xs,[],Ys).
  560
  561
  562%= 	 	 
 appendAttributes(?Ctx, ?L, ?R, ?AA) is semidet
Append Attributes.
  568appendAttributes(_Ctx,L,R,AA):-quietly((mergeAppend0(L,R,A),list_to_set_safe(A,AA))),!.
  569
  570
  571%= 	 	 
 mergeAppend0(:TermL, ?R, ?R) is semidet
Merge Append Primary Helper.
  577mergeAppend0(L,R,R):-var(L),!,var(R),!.
  578mergeAppend0(L,R,A):-var(R),append(L,R,A),!.
  579mergeAppend0(L,R,A):-var(L),append(L,R,A),!.
  580mergeAppend0(L,[R|RR],A):-eqmember(R,L),mergeAppend0(L,RR,A).
  581mergeAppend0([L|LL],R,A):-eqmember(L,R),mergeAppend0(LL,R,A).
  582mergeAppend0(L,R,A):-append(L,R,A).
  583
  584
  585%= 	 	 
 eqmember(?E, ?List) is semidet
Eqmember.
  591eqmember(E,List):-copy_term_numvars(E:List,E0:List0),member(E0,List0).
  592
  593%= 	 	 
 copy_term_numvars(?OLD, ?NEW) is semidet
Copy Term Numvars.
  599copy_term_numvars(OLD,NEWO):-copy_term_nat(OLD,NEW),numbervars(NEW,0,_),!,NEW=NEWO