
RuleBase("<-",{left,right});
HoldArg("<-",left);
HoldArg("<-",right);

Set(LocResult,True);
10 # LocPredicate(exp_IsAtom) <--
[
  Local(tr,result);
  tr:=patterns;
  result:=False;
  While (tr != {})
  [
    If (Head(Head(tr)) = exp,
    [
      Set(LocResult,Eval(Head(Tail(Head(tr)))));
      result := True;
      tr:={};
    ],
    [
      tr := Tail(tr);
    ]);
  ];
  result;
];

10 # LocPredicate(exp_IsFunction) <--
[
  Local(tr,result,head);
  tr:=patterns;
  result:=False;
  While (tr != {})
  [
    Set(head, Head(Head(tr)));
    If (Not(IsAtom(head)) And exp[0]=head[1] And PatternMatches(head[2], exp),
    [
      Set(LocResult,Eval(Head(Tail(Head(tr)))));
      Set(result, True);
      Set(tr,{});
    ],
    [
      Set(tr, Tail(tr));
    ]);
  ];
  result;
];
20 # LocPredicate(_exp) <-- False;

LocChange(_exp) <-- LocResult;
/*TODO remove!
10 # LocChange(exp_IsAtom) <-- 
[
  Local(tr,result);
  tr:=patterns;
  result:=False;
  While (tr != {})
  [
    If (Head(Head(tr)) = exp,
    [
      result := Eval(Head(Tail(Head(tr))));
      If(Verbose, Echo({exp," replaced with ",result}));
      tr:={};
    ],
    [
      tr := Tail(tr);
    ]);
  ];
  result;
];

10 # LocChange(exp_IsFunction) <--
[
  Local(tr,result,head);
  tr:=patterns;
  result:=False;
  While (tr != {})
  [
    head := Head(Head(tr));
    If (Not(IsAtom(head)) And exp[0]=head[1] And PatternMatches(head[2], exp),
    [
      result := Eval(Head(Tail(Head(tr))));
      If(Verbose, Echo({exp," replaced with ",result}));
      tr:={};
    ],
    [
      tr := Tail(tr);
    ]);
  ];
  result;
];
*/

UnFence("LocPredicate",1);
UnFence("LocChange",1);

10 # LocProcessSingle({_pat,_post,_exp}) <-- { {pat[0],PatternCreate(pat,post)},exp };
20 # LocProcessSingle({pat_IsFunction,_exp}) <-- { {pat[0],PatternCreate(pat,True)},exp };
30 # LocProcessSingle({pat_IsAtom,_exp}) <-- { pat,exp };
40 # LocProcessSingle(pat_IsFunction <- _exp) <-- { {pat[0],PatternCreate(pat,True)},exp };
50 # LocProcessSingle(pat_IsAtom <- _exp) <-- { pat,exp };

LocProcess(patterns) :=
[
  MapSingle("LocProcessSingle",patterns);
];

CompilePatterns(patterns) := LocPatterns(LocProcess(patterns));


5 # (_expression /: LocPatterns(_patterns)) <--
[
  Substitute(expression,"LocPredicate","LocChange");
];
10 # (_expression /: _patterns) <--
[
  Set(patterns, LocProcess(patterns));
  Substitute(expression,"LocPredicate","LocChange");
];

5 # (_expression /:: LocPatterns(_patterns)) <--
[
  Substitute(expression,"LocPredicate","LocChange");
];
10 # (_expression /:: _patterns) <--
[
  Local(old);
  Set(patterns, LocProcess(patterns));
  Set(old, expression);
  Set(expression, Substitute(expression,"LocPredicate","LocChange"));
  While (expression != old)
  [
    Set(old, expression);
    Set(expression, Substitute(expression,"LocPredicate","LocChange"));
  ];
  expression;
];


