anchor.diff:  
   -export([format_error/1]).
   
  --export([module/1,patterns/1,add_docs_module/1]).
  +-export([module/1,function_patterns/1,macro_patterns/1,add_docs_module/1]).
   
   -import(beam_lib, [all_chunks/1,build_module/1,chunks/2]).
   -import(lfe_lib, [is_proper_list/1,is_symb_list/1]).
  --import(lists, [filter/2,foldl/3,reverse/1]).
  --import(ordsets, [is_element/2]).
  +-import(lists, [member/2,filter/2,foldl/3,reverse/1]).
   -import(proplists, [delete/2,get_value/3]).
   
   -include("lfe_comp.hrl").
  
positive.code:       Line :: non_neg_integer(),
        Error :: {bad_lambda,[_]}.
  do_module(Docs, [{['define-function',Name,Body,DocStr],Line}|Defs]) ->
      ?DO_MOD(Docs,function,Name,Body,DocStr,Line,Defs);
  do_module(Docs, [{['define-macro',Name,Body,DocStr],Line}|Defs]) ->
      ?DO_MOD(Docs,macro,Name,Body,DocStr,Line,Defs);
  do_module(Docs, [_|Defs]) -> do_module(Docs, Defs);
  do_module(Docs, [])       -> Docs.
  
  %% exclude(Name | {Name,Arity}) -> boolean().
  %%  Return true if a function should be excluded from the docs chunk.
  
  -spec exclude(Name | {Name,Arity}) -> boolean() when
        Name  :: atom(),
        Arity :: non_neg_integer().
  exclude({'LFE-EXPAND-EXPORTED-MACRO',3}) -> true;
  exclude('MODULE')                        -> true;
  exclude(_)                               -> false.
  
  %% patterns(LambdaForm) -> no | {yes,Arity,Patterns}.
  %%  Given a {match-,}lambda form, attempt to return its patterns (or arglist).
  %%  N.B. A guard is appended to its pattern and Patterns is a list of lists.
  
  -spec patterns(LambdaForm) -> 'no' | {'yes',Arity,Patterns} when
        LambdaForm :: nonempty_list(),
        Arity      :: non_neg_integer(),
        Patterns   :: nonempty_list(pattern()).
  patterns([lambda,Args|_]) ->
      ?IF(is_symb_list(Args), {yes,length(Args),[Args]}, no);
  patterns(['match-lambda',[[[list|Pat],'$ENV'],['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(length(Pat), [Pat++[Guard]], Cls),
          do_patterns(255, [Pat], Cls));
  patterns(['match-lambda',[[Pat,'$ENV'],['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(length(Pat), [Pat++[Guard]], Cls),
          do_patterns(255, [Pat], Cls));
  patterns(['match-lambda',[[[list|Pat],'$ENV']|_]|Cls]) ->
      ?IF(is_proper_list(Pat), do_patterns(length(Pat), [Pat], Cls), no);
  patterns(['match-lambda',[[Pat,'$ENV']|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(length(Pat), [Pat], Cls),
          do_patterns(255, [Pat], Cls));
  patterns(['match-lambda',[Pat,['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat), do_patterns(length(Pat), [Pat++[Guard]], Cls), no);
  patterns(['match-lambda',[Pat|_]|Cls]) ->
      ?IF(is_proper_list(Pat), do_patterns(length(Pat), [Pat], Cls), no);
  patterns(_) -> no.
  
  -spec do_patterns(Arity, Patterns, Forms) -> 'no' | {'yes',Arity,Patterns} when
        Arity    :: non_neg_integer(),
        Patterns :: nonempty_list(pattern()),
        Forms    :: list().
  do_patterns(N, Acc, [[[[list|Pat],'$ENV'],['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat++[Guard]|Acc], Cls),
          do_patterns(255, [Pat++[Guard]|Acc], Cls));
  do_patterns(N, Acc, [[[Pat,'$ENV'],['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat++[Guard]|Acc], Cls),
          do_patterns(255, [Pat++[Guard]|Acc], Cls));
  do_patterns(N, Acc, [[[[list|Pat],'$ENV']|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat|Acc], Cls),
          do_patterns(255, [Pat|Acc], Cls));
  do_patterns(N, Acc, [[[Pat,'$ENV']|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat|Acc], Cls),
          do_patterns(255, [Pat|Acc], Cls));
  do_patterns(N, Acc, [[Pat,['when'|_]=Guard|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat++[Guard]|Acc], Cls),
          no);
  do_patterns(N, Acc, [[Pat|_]|Cls]) ->
      ?IF(is_proper_list(Pat),
          do_patterns(?IF(N =:= length(Pat), N, 255), [Pat|Acc], Cls),
          no);
  do_patterns(N, Acc, []) -> {yes,N,reverse(Acc)};
  do_patterns(_, _, _) -> no.
  
  %% make_doc(Type, Name, Arity, Patterns, Doc, Line) -> doc().
  %%  Convenience constructor for #doc{}, which is defined in src/lfe_doc.hrl.
  
negative.code:       ModDoc :: binary().
  exports_attributes(#module{name=Name,code=Beam,docs=Docs0}=Mod) ->
      ChunkRefs = [exports,attributes],
      {ok,{Name,[{exports,Expf},{attributes,Attr}]}} = chunks(Beam, ChunkRefs),
      Expm  = get_value('export-macro', Attr, []),
      MDoc  = iolist_to_binary(get_value(doc, Attr, "")),
      Docs1 = foldl(do_exports(Expf, Expm), [], Docs0),
      {MDoc,Mod#module{docs=Docs1}}.
  
  %% do_exports(Expf, Expm) -> Fun.
  %%  Close over Expf and Expm then return the folding function for
  %%  exports/1.  We only included exported functions and macros.  The
  %%  export-macro attribute is not necessarily sorted.
  -spec do_exports(Expf, Expm) -> Fun when
        Expf :: [{atom(),non_neg_integer()}],
        Expm :: [atom()],
        Fun  :: fun((doc(), [doc()]) -> [doc()]).
  
  do_exports(Expf, Expm) ->
      fun (#doc{type=function,name=F,arity=A}=Doc, Docs) ->
              ?IF(member({F,A}, Expf),
                  [Doc#doc{exported=true}|Docs],
                  Docs);
          (#doc{type=macro,name=M}=Doc, Docs) ->
              ?IF(member(M, Expm),
                  [Doc#doc{exported=true}|Docs],
                  Docs)
      end.
  
  %% add_beam_chunk(Bin, Id, ChunkData) -> Bin.
  