anchor.diff:  -import(ordsets, [add_element/2,del_element/2,is_element/2,
   		  union/1,union/2,intersection/2,subtract/2]).
   -import(cerl, [ann_c_cons/3,ann_c_cons_skel/3,ann_c_tuple/2,c_tuple/1,
  -	       ann_c_map/2, ann_c_map/3]).
  +	       ann_c_map/3]).
   
   -include("core_parse.hrl").
   
  
positive.code: upattern(#c_map{es=Es0}=Map, Ks, St0) ->
      {Es1,Esg,Esv,Eus,St1} = upattern_list(Es0, Ks, St0),
      {Map#c_map{es=Es1},Esg,Esv,Eus,St1};
  upattern(#c_map_pair{op=#c_literal{val=exact},val=V0}=MapPair, Ks, St0) ->
      {V,Vg,Vv,Vu,St1} = upattern(V0, Ks, St0),
      {MapPair#c_map_pair{val=V},Vg,Vv,Vu,St1};
  upattern(#c_binary{segments=Es0}=Bin, Ks, St0) ->
      {Es1,Esg,Esv,Eus,St1} = upat_bin(Es0, Ks, St0),
      {Bin#c_binary{segments=Es1},Esg,Esv,Eus,St1};
  
negative.code: 		    Fc = fail_clause([Fpat], A, #c_literal{val=badarg}),
  		    {#icase{anno=#a{anno=A},args=[M1],clauses=Cs,fc=Fc},Mps,St3};
  		{_,_} ->
  		    {M2,Eps,St2} = map_build_pair_chain(M1,Es0,A,St1),
  		    {M2,Mps++Eps,St2}
  	    end;
  	false -> throw({bad_map,bad_map})
      end.
  
  %% Group continuous literal blocks and single variables, i.e.
  %% M0#{ a := 1, b := V1, K1 := V2, K2 := 42}
  %% becomes equivalent to
  %% M1 = M0#{ a := 1, b := V1 },
  %% M2 = M1#{ K1 := V1 },
  %% M3 = M2#{ K2 := 42 }
  
  map_build_pair_chain(M,Es,A,St) ->
      map_build_pair_chain(M,Es,A,St,[]).
  
  map_build_pair_chain(M0,[],_,St,Mps) ->
      {M0,Mps,St};
  map_build_pair_chain(M0,Es0,A,St0,Mps) ->
      % group continuous literal blocks
      % Anno = #a{anno=[compiler_generated]},
      % order is important, we need to reverse the literals
      case map_pair_block(Es0,[],[],St0) of
  	{{CesL,EspL},{[],[]},Es1,St1} ->
  	    {MVar,St2} = new_var(St1),
  	    Pre = [#iset{var=MVar, arg=ann_c_map(A,M0,reverse(CesL))}],
  	    map_build_pair_chain(MVar,Es1,A,St2,Mps++EspL++Pre);
  	{{[],[]},{CesV,EspV},Es1,St1} ->
  	    {MVar,St2} = new_var(St1),
  	    Pre = [#iset{var=MVar, arg=#c_map{arg=M0,es=CesV, anno=A}}],
  	    map_build_pair_chain(MVar,Es1,A,St2,Mps ++ EspV++Pre);
  	{{CesL,EspL},{CesV,EspV},Es1,St1} ->
  	    {MVarL,St2} = new_var(St1),
  	    {MVarV,St3} = new_var(St2),
  	    Pre = [#iset{var=MVarL, arg=ann_c_map(A,M0,reverse(CesL))},
  		   #iset{var=MVarV, arg=#c_map{arg=MVarL,es=CesV,anno=A}}],
  	    map_build_pair_chain(MVarV,Es1,A,St3,Mps++EspL++EspV++Pre)
      end.
  
  map_pair_block([{Op,L,K0,V0}|Es],Ces,Esp,St0) ->
      {K,Ep0,St1} = safe(K0, St0),
      {V,Ep1,St2} = safe(V0, St1),
      A = lineno_anno(L, St2),
      Pair0 = map_op_to_c_map_pair(Op),
      Pair1 = Pair0#c_map_pair{anno=A,key=K,val=V},
      case cerl:is_c_var(K) of
  	false ->
  	    map_pair_block(Es,[Pair1|Ces],Ep0 ++ Ep1 ++ Esp,St2);
  	true ->
  	    {{Ces,Esp},{[Pair1],Ep0++Ep1},Es,St2}
      end;
  map_pair_block([],Ces,Esp,St) ->
      {{Ces,Esp},{[],[]},[],St}.
  
  map_op_to_c_map_pair(map_field_assoc) -> #c_map_pair{op=#c_literal{val=assoc}};
  map_op_to_c_map_pair(map_field_exact) -> #c_map_pair{op=#c_literal{val=exact}}.
  
  is_valid_map_src(#c_literal{val = M}) when is_map(M) -> true;
  is_valid_map_src(#c_var{})  -> true;
  is_valid_map_src(_)         -> false.
  
  %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}.
  
  