typing

Thomas Arts <>
Thu Aug 24 10:00:35 CEST 2000


Francesco Cesarini wrote:


> Not that I have seen it being used in major projects, but in 1995 I was
> using a little parser written by Hans at the CS lab. It chugged through
> a set of modules and returned all the atoms which appeared only once in
> the code, [together with their module and line number ?]. It helped
> detect most of the misspelt atom errors. If this program is still
> around, (or some one with the time wants to rewrite it), it would be
> great if it was added to the contributions section.


That's not so hard to write. See attached source code. Please test it
for me, since that's not done yet.

uniqatom.erl can be used to find all uniquely appearing atoms in a file
(that is to say, functions and record names are not considered to be atoms
in this).

uniqatom:check(FileName).

please use a string with extension .erl as FileName (e.g. "uniqatom.erl").

Best regards
Thomas
-------------- next part --------------
%
% Thomas Arts
% 20000824
%

-module(uniqatom).

-export([check/1,uniques/2]).

-import(lists,[foldl/3]).

check(FileName) ->
  Dir = filename:dirname(FileName),
  Module = filename:basename(FileName,".erl"),
  case epp:parse_file(FileName,[Dir],[]) of
       {ok,AbsForms} ->
         Atoms = 
           foldl(fun(AbsForm,As) ->
                    collect(AbsForm)++As
                 end,[],AbsForms),
         [ "line "++integer_to_list(Line)++": "++atom_to_list(Atom) ||
                                       {atom,Line,Atom}<-uniques(Atoms,[]) ];
       {error,ErrorDesc} ->
         exit({?MODULE,"cannot read file "++FileName})
  end.

uniques([],_) ->
  [];
uniques([H|T],Doubles) ->
  case member(H,T) of
       true ->
         uniques(T,[H|Doubles]);
       false ->
         case member(H,Doubles) of
              true ->
                uniques(T,Doubles);
              false ->
                [H|uniques(T,Doubles)]
         end
  end.

member(_,[]) ->
  false;
member({atom,_,Atom},[{atom,_,Atom}|_]) ->
  true;
member(Atom,[_|Atoms]) ->
  member(Atom,Atoms).

collect(AbsForm) ->
  case AbsForm of
       {function,Line,Name,Arity,Body} ->
         atoms(Body);
       _ ->
         []
  end.

atoms(Expr) -> 
 case Expr of
      {atom,_,Atom} ->
        [Expr];
      {tuple,_,Exprs} ->
         atoms(Exprs);
      {cons,_,Head,Tail} ->
         atoms([Head,Tail]);
      {lc,_,E,GenFils} ->
         atoms([E|GenFils]);
      {generate,_,Expr1,Expr2} ->
         atoms([Expr1,Expr2]);
      {clause,_,Patterns,Guards,Body} ->
         atoms(Patterns++Guards++Body);
      {'case',_,E,Clauses} ->
         atoms([E|Clauses]);
      [] ->
         [];
      [E|Es] ->
         atoms(E)++atoms(Es);
      {block,_,Exprs} ->
         atoms(Exprs);
      {match,_,Expr1,Expr2} ->
         atoms([Expr1,Expr2]);
      {'if',_,Clauses} ->
         atoms(Clauses);
      {'receive',_,Clauses} ->
         atoms(Clauses);
      {'receive',_,Clauses,TimeOut,Args} ->
         atoms(Clauses++Args);
      {'catch',_,Arg} ->
         atoms(Arg);
      {'throw',_,Arg} ->
         atoms(Arg);
      {call,_,Func,Args} ->
         atoms(Args);
      {op,_,Name,Arg} ->
         atoms(Arg);
      {op,_,Name,Arg1,Arg2} ->
         atoms([Arg1,Arg2]);
      {'fun',_,{clauses,Clauses}} ->
         atoms(Clauses);
      {record,_,Name,Fields} ->
         atoms(Fields);
      {record,_,Record,Name,Fields} ->
         atoms([Record|Fields]);
      {record_field,_,Name,E} ->
         atoms(E);
      {record_index,_,Record,Name,_} ->
         atoms(Record);
      _ -> 
         []
  end.


More information about the erlang-questions mailing list