anchor.diff:      %% while still being agnostic about the erl_parse tree format.
       %% I think I only rely on same representation of atoms
       %% (which do have a line number though...)
  -    subst_meta_var_values(
  -      substitute(
  -        erl_parse:abstract(
  -          erl_syntax:revert(
  -            erl_syntax:function(FnNameExprPlaceholder, FnClauses))),
  -        erl_syntax:revert(FnNameExprPlaceholder),
  -        FnNameExpr)).
  +    subst_atom(
  +      erl_parse:abstract(
  +        erl_syntax:revert(
  +          erl_syntax:function(FnNameExprPlaceholder, FnClauses))),
  +      erl_syntax:revert(FnNameExprPlaceholder),
  +      FnNameExpr).
   
   find_function_clauses([Form | Rest], FnName, Arity) ->
       case erl_syntax:type(Form) of
  
positive.code: find_function_clauses([], FnName, Arity) ->
      erlang:error({reference_to_undefined_function,FnName,Arity}).
  
  substitute(Term, TermToBeChanged, NewTerm) ->
      map_term(fun(Node) ->
                       if Node =:= TermToBeChanged -> NewTerm;
                          true                     -> Node
                       end
               end,
               Term).
  
  subst_meta_var_values(Term) ->
      map_term(fun try_subst_meta_var_value/1, Term).
  
  map_term(F, [Term | Rest]) ->
      case F(Term) of
  
negative.code:     case erl_syntax_lib:analyze_application(Node) of
          {?MODULE, {mk_fn, 2}} ->
              [FnNameExpr, FnDef] = erl_syntax:application_arguments(Node),
              transform_mk_fn(FnNameExpr, FnDef, [], Forms);
          {?MODULE, {mk_fn, 3}} ->
              [FnNameExpr, FnDef, RuntimeTransforms] =
                  erl_syntax:application_arguments(Node),
              transform_mk_fn(FnNameExpr, FnDef, [RuntimeTransforms], Forms);
          _X ->
              Node
      end;
  transform_node(_Type, Node, _Forms) ->
      Node.
  
  
  %% transform a "call" to gpb_codegen:mk_fn(Name, Def)
  %% return a parse-tree for an expression that produces a
  %% a parse-tree for a function definition
  transform_mk_fn(FnNameExpr, DefAsFun, RuntimeTransforms, AllForms) ->
      case erl_syntax:type(DefAsFun) of
          fun_expr ->
              FnClauses = erl_syntax:fun_expr_clauses(DefAsFun),
              mk_apply(
                ?MODULE, runtime_transform,
                [mk_partly_abstract_function(FnNameExpr, FnClauses)
                 | RuntimeTransforms]);
          implicit_fun ->
              case analyze_implicit_fun_name(DefAsFun) of
                  {DFnName, Arity} when is_integer(Arity) ->
                      FnClauses = find_function_clauses(AllForms, DFnName, Arity),
                      mk_apply(
                        ?MODULE, runtime_transform,
                        [mk_partly_abstract_function(FnNameExpr, FnClauses)
                         | RuntimeTransforms]);
                  {Module, {FnName, Arity}} ->
                      erlang:error({?MODULE,not_supported,mk_fn,remote_fn,
                                    ?ff("~p:~p/~w", [Module, FnName, Arity])})
  