anchor.diff:  %% how about expressions has side effects?
   variable_replaceable(Exp) ->
       case lists:keysearch(category, 1, refac_syntax:get_ann(Exp)) of
  -      {value, {category, record_field}} -> false;
  -      {value, {category, record_type}} -> false;
  -      {value, {category, guard_expression}} -> false;
  -      {value, {category, macro_name}} -> false;
  -      {value, {category, pattern}} ->
  -	  case refac_syntax:is_literal(Exp) orelse
  -		 refac_syntax:type(Exp) == variable
  -	      of
  -	    true ->
  -		true;
  -	    _ -> false
  -	  end;
  -      _ -> T = refac_syntax:type(Exp),
  -	   not lists:member(T, [match_expr, operator]) andalso
  -	     refac_util:get_var_exports(Exp) == []
  +	{value, {category, record_field}} -> false;
  +	{value, {category, record_type}} -> false;
  +	{value, {category, guard_expression}} -> false;
  +	{value, {category, macro_name}} -> false;
  +	{value, {category, pattern}} ->
  +	    case refac_syntax:is_literal(Exp) orelse
  +		refac_syntax:type(Exp) == variable
  +	    of
  +		true ->
  +		    true;
  +		_ -> false
  +	    end;
  +      _ -> 
  +	    T = refac_syntax:type(Exp),
  +	    not lists:member(T, [match_expr, operator]) andalso
  +		refac_util:get_var_exports(Exp) == []
       end.
   
   
  
positive.code: sim_expr_search(FName, Start = {Line, Col}, End = {Line1, Col1}, SimiScore0, SearchPaths, TabWidth) ->
      ?wrangler_io("\nCMD: ~p:sim_expr_search(~p, {~p,~p},{~p,~p},~p, ~p, ~p).\n",
  		 [?MODULE, FName, Line, Col, Line1, Col1, SimiScore0, SearchPaths, TabWidth]),
      SimiScore1 = try
  		   case SimiScore0 of
  		     [] -> ?DefaultSimiScore;
  		     _ -> list_to_float(SimiScore0)
  		   end
  		 catch
  		   V -> V;
  		   _:_ -> throw({error, "Parameter input is invalid."})
  		 end,
      SimiScore = case SimiScore1 >= 0.1 andalso SimiScore1 =< 1.0 of
  		  true -> SimiScore1;
  		  _ -> ?DefaultSimiScore
  		end,
      {ok, {AnnAST, _Info}} = refac_util:parse_annotate_file(FName, true, [], TabWidth),
      case refac_util:pos_to_fun_def(AnnAST, Start) of
        {ok, FunDef} -> FunDef;
        {error, _} -> throw({error, "You have not selected an expression!"}),
  		    FunDef = []
      end,
      Exprs = refac_util:pos_to_expr_list(FunDef, Start, End),
      case Exprs of
        [] -> throw({error, "You have not selected an expression!"});
        _ -> ok
      end,
      RecordInfo = get_module_record_info(FName, SearchPaths, TabWidth),
      Exprs1 = case Exprs of
  	       [E] -> normalise_expr(E, RecordInfo);
  	       [_| _] ->
  		   normalise_expr(Exprs, RecordInfo)
  	     end,
      Res = do_search_similar_expr(AnnAST, RecordInfo, Exprs1, SimiScore),
      {Ranges, ExportVars, SubSt} = lists:unzip3(Res),
      SE = get_start_end_loc(Exprs),
      Ranges1 = [SE| Ranges -- [SE]],
      ExportVars1 = {element(1, lists:unzip(vars_to_export(FunDef, End, Exprs1))), lists:usort(lists:append(ExportVars))},
      AntiUnifier = generalise_expr(Exprs1, SubSt, ExportVars1),
      %% AntiUnifier = denormalise_expr(generalise_expr(Exprs1,SubSt, ExportVars1),RecordInfo),
      Num = length(Ranges1),
      case Num =< 1 of
        true -> ?wrangler_io("No similar expression has been found.\n", []);
        false -> ?wrangler_io("~p expressions (including the expression selected)"
  			    " which are similar to the expression selected have been found. \n", [Num]),
  	       ?wrangler_io(compose_search_result_info(FName, Ranges1), []),
  	       ?wrangler_io("\nThe generalised expression would be:\n\n~s\n\n", [refac_prettypr:format(AntiUnifier)]),
  	       ?wrangler_io("\nUse 'C-c C-e' to remove highlights!\n", []),
  	       {ok, Ranges1}
      end.
     
  
  
  do_search_similar_expr(AnnAST, RecordInfo, Exprs, SimiScore) when is_list(Exprs) ->
      F0 = fun (FunNode, Acc) ->
  		 F = fun (T, Acc1) ->
  			     case refac_syntax:type(T) of
  			       clause -> Exprs1 = refac_syntax:clause_body(T),
  					 do_search_similar_expr_1(Exprs, Exprs1, RecordInfo, SimiScore, FunNode) ++ Acc1;
  			       block_expr -> Exprs1 = refac_syntax:block_expr_body(T),
  					     do_search_similar_expr_1(Exprs, Exprs1, RecordInfo, SimiScore, FunNode) ++ Acc1;
  			       try_expr -> Exprs1 = refac_syntax:try_expr_body(T),
  					   do_search_similar_expr_1(Exprs, Exprs1, RecordInfo, SimiScore, FunNode) ++ Acc1;
  			       _ -> Acc1
  			     end
  		     end,
  		 refac_syntax_lib:fold(F, Acc, FunNode)
  	 end,
      F1 = fun (Node, Acc) ->
  		 case refac_syntax:type(Node) of
  		   function -> F0(Node, Acc);
  		   _ -> Acc
  		 end
  	 end,
      lists:reverse(refac_syntax_lib:fold(F1, [], AnnAST));
  
  do_search_similar_expr(AnnAST, RecordInfo, Expr, SimiScore) ->
      {EStart, EEnd} = get_start_end_loc(Expr),
      F0 = fun (FunNode, Acc) ->
  		 F = fun (Node, Acc1) ->
  			     case refac_util:is_expr(Node) of
  			       true ->
  				   {NStart, NEnd} = get_start_end_loc(Node),
  				   case EStart =< NStart andalso NEnd =< EEnd orelse
  					  NStart =< EStart andalso EEnd =< NEnd
  				       of
  				     true -> Acc1;
  				     _ ->
  					 Node1 = normalise_expr(Node, RecordInfo),
  					 ExportVars = vars_to_export(FunNode, NEnd, Node),
  					 find_anti_unifier(Expr, Node1, SimiScore, ExportVars) ++ Acc1
  				   end;
  			       _ -> Acc1
  			     end
  		     end,
  		 refac_syntax_lib:fold(F, Acc, FunNode)
  	 end,
      F1 = fun (Node, Acc) ->
  		 case refac_syntax:type(Node) of
  		   function -> F0(Node, Acc);
  		   _ -> Acc
  		 end
  	 end,
      lists:reverse(refac_syntax_lib:fold(F1, [], AnnAST)).
     
  
   
  do_search_similar_expr_1(Exprs1, Exprs2, RecordInfo, SimiScore, FunNode) ->
      Len1 = length(Exprs1),
      Len2 = length(Exprs2),
      case Len1 =< Len2 of
        true -> Exprs21 = lists:sublist(Exprs2, Len1),
  	      {S1, E1} = get_start_end_loc(Exprs1),
  	      {S2, E2} = get_start_end_loc(Exprs21),
  	      case S1 =< S2 andalso E2 =< E1 orelse S2 =< S1 andalso E1 =< E2 of
  		true -> [];
  		_ ->
  		    ExportVars = vars_to_export(FunNode, E2, Exprs21),
  		    find_anti_unifier(Exprs1, normalise_expr(Exprs21, RecordInfo), SimiScore, ExportVars)
  		      ++ do_search_similar_expr_1(Exprs1, tl(Exprs2), RecordInfo, SimiScore, FunNode)
  	      end;
        _ -> []
      end.
  
  
  find_anti_unifier(Expr1, Expr2, SimiScore, Expr2ExportVars) ->
      try
        do_find_anti_unifier(Expr1, Expr2)
      of
        SubSt ->
  	    {SubExprs1, SubExprs2} = lists:unzip(SubSt),
  
negative.code: 
  -export([get_start_end_loc/1, start_counter_process/0, 
  	 stop_counter_process/1, gen_new_var_name/1,
  	 variable_replaceable/1, find_anti_unifier/5,
  	 generalise_expr/3, vars_to_export/3]).
  
  -import(refac_duplicated_code, [collect_vars/1]).
  -import(refac_expr_search, [compose_search_result_info/1]).
  
  -include("../include/wrangler.hrl").
  
  