My bad opinions

2012/01/10

Obfuscation

Late Promises

For a long while now, I've showed various people what I consider to be one of the most twisted bits of obfuscated Erlang to have been written. I've had it for a bit over a year, and showed it to a bunch of Erlang people back at the Erlang User Conference in Sweden back in 2011.

I then promised to write a blog post about it and explaining how I wrote it, which I promptly deferred to later in one brave act of procrastination. I decided to finally put the whole thing together, between the writing of a new Learn You Some Erlang chapter, the formatting of an older one for a publisher, and work.

The code you'll see below is something I wrote when I was still working for Erlang Solutions Ltd. (I now work for a place called BLOOM Digital Platforms, still in Erlang). When working for ESL, I would spend quite some time traveling around the world to go teach courses about Erlang to different people and businesses. This did include its share of long airport waiting times, long pauses in hotels without WiFi access, and bus rides. That's where I took the time and fun challenge to write the messiest Erlang code possible, using features mostly unique to the language.

What does it look like?

I'll be quick—it looks like this (alternatively, a gist!):

                                          %%%%%%%                      %%%%%%
-module (        obfuscation            %%       %%%               %%%       %%
)                                           %%%%%%\ %             % /%%%%%%
. -compile(                                 %%   %%       ' '       %%   %%
[export_all  ] ) . -define(swap          %  %%%%%%%        |        %%%%%%%  %
(A,                                       %%%              .              %%%
B), B                                                      %
A                                                       %%   %%
). -define(M,                                                                                    ?MODULE). -define(v, 
o).            -define(p,().                           %%%%%%%%%%
                             -define(q,           %%%%%  ,,__,,  %%%%
)).                                               %%%    |    |   %%%
     -define(s                                    %%     \ _ / %   %%
,,).               -define('.   ',             {           %    %
                  ).                                      %%%    %
                                -define(' .  ',        }     ). %%%%%%%%%%%%%%%%
-define(      ' \''                                             % LL  OOO LLL  %
            ,                                                   % L L  O  L    %
               integer).                                        % L L  O  LLL  %
                -define(':('                                    % L L  O  L    %
,                                                               % LL  OOO LLL  %
 atom                                                           %%%%%%%%%%%%%%%%
,
)
.                                         -define(
':)'                       ,       tuple,     ). -define('}',
[
).            -define('{'    ,

]                                                 )     .

%% According to many Haskellers, type signatures represent sufficient
%% documentation. I have thus provided the type signature to the main
%% function of this program, hoping its self-describing nature and the
%% types will be enough to enlighten the readers of this code as to its
%% purpose and inner workings.
%%                                               Best Regards,
%%                                               - Ferd.
-spec main() -> ''.
main?p  ?q  -> main?p atom ?q . main?p Bin ?q  ->
    '. _   '?p Bin ?q  ?s S= ?p ?p fun '! _/?  - '/1 ?q ?p ?p ?p fun '_ _/-  - '/1 
    ?q ?p ?p ?p fun '! _/?  - '/1 ?q ?p ?p ?p fun '_ _/-  _ '/1 ?q ?p ?p ?p fun
    '_ _/-  - '/1 ?q ?p ?p ?p fun '! _/?  - '/1 ?q ?p ?p ?p fun '_ _/-  _ '/1 ?q ?p ?p ?p
    fun '! _/-  - '/1 ?q ?p ?M:'_  ='?p ?M:'=  _'?p ?M:'_  ='?p ".Ub-ry rWby" ?q
    ?q  ?q  ?q ?q ?p ?p ?p fun '! _/-  - '/1 ?q ?p  ?'}' $\n,$\n ?'{'  ?q  ?q ?p ?M:'_  ='?p
    ?M:'=  _'?p "Ug-.y"?swap("r","r")"ebbyoE " ?q  ?q  ?q  ?q  ?q ?q ?p
     ?'}' $\n,$\n ?'{'  ?q  ?q ?q ?p ?p ?p fun '! _/-  - '/1 ?q ?p ?M:'=  _'?p ?M:'_  ='?p
    ". agrbu "?swap("s","g")" vtkh og ur" ?q  ?q  ?q  ?q ?p ?M:'_  ='?p
    ?M:'=  _'?p "Vq-tfr arnrzgn hn ul bg" ?q  ?q  ?q  ?q  ?q ?q ?p  ?'}' $\n,$\n ?'{' 
    ?q  ?q ?q ?p ?M:'=  _'?p ?M:'=  _'?p ?M:'=  _'?p "-yvf.,syLnarl " ?q  ?q
    ?q  ?q  ?q ?q ?p   ?'}' $\n,$\n ?'{'  ?q  ?q ?q ?p ?M:'=  _'?p ?M:'_  ='?p "**xppyv"
    ?q  ?q  ?q  ?q ?q ?p  ?'}' $\n ?'{'  ?q  ?s group_leader?p  ?q  !  ?'.   ' io_request, self?p
    ?q , '$',  ?'.   ' put_chars, unicode, S ?' .  '  ?' .  '  ?s ''.

'! _/?  - '?p A ?q  -> fun?p B ?q  -> ?p fun erlang:'++'/2 ?q ?p A,B ?q  end. '_ _/-  - '
?p A ?q  -> '! _/?  - '?p A ?q . '_ _/-  _ '?p A ?q  -> '! _/?  - '?p A ?q . '! _/-  - '?p B ?q
-> fun?p A ?q  -> ?p ?p ?p fun '! _/?  - '/1 ?q ?p A ?q  ?q ?q ?p B ?q  end.

%%%%%%%%%%%%%%%%%
%%%%%       %%%%%   %%%%%%%%%%%%%%%  %%    %%  %%%%%%%%   %%%%%%
%%%%%       %%%%%   %%%%%%%%%%%%%%%  %%    %%     %%     %%
%%%%%       %%%%%         % %        %% %% %%     %%      %%%%%
%%%%%       %%%%%         % %        %% %% %%     %%       %%%%
%               %         % %        %%    %%     %%          %%
%%%           %%%         % %        %%    %%  %%%%%%%%  %%%%%%
%%%%%       %%%%%
%%%%%%%   %%%%%%%           - WAY -
%%%%%%%% %%%%%%%%
%%%%%%%%%%%%%%%%%                                       [skip to the end for infos]





-define('             ,', ?'.   '  ?' \'' ,0,303 ?' .  '  ?s ?'.   ' cons,0 ?s
?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,303
?' .  ' ,    ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s          ?'.   '
nil,0 ?' .  '  ?' .  '  ?s  ?'.   ' cons,0 ?s ?'.   ' cons,0 ?s ?'.   '  ?':)'
 0 ?s  ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s ?'.   '  ?' \'' ,0,303 ?' .  '  ?s
?'.   '  ?':(' 0,'andalso'
?' .  '  ?s ?'.   '  ?':)'
0 ?s  ?'}'  ?'.   '  ?':('
0,op ?' .  '  ?s   ?'.   '
  ?' \'' ,0,303 ?' .  '  ?s
?'.   '  ?':(' 0,'>=' ?' .  '  ?s
?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  '
, ?'.   '  ?' \'' ,0,303 ?' .  ' , ?'.   '  ?':(' 0,'C'
 ?' .  '  ?'{'  ?' .  '  ?s ?'.   '  ?':)' 0 ?s    ?'}'
?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \'' ,0,303
?' .  ' , ?'.   '  ?' \'' ,0,65 ?' .  '  ?'{'  ?' .  '
  ?'{'  ?' .  '  ?s ?'.   '  ?':)' 0 ?s ?'}'  ?'.   '
  ?':(' 0,op ?' .  '  ?s
?'.   '  ?' \'' ,0, 303 
?' .  '  ?s ?'.   '  ?':('
 0,'=<' ?' .  '  ?s ?'.   '
  ?':)' 0,   ?'}'  ?'.   '
  ?':(' 0,var ?' .  '   ,
 ?'.   '  ?' \'' ,0,   303
?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s ?'.   '  ?':)' 0 ?s
?'}'  ?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \'' ,0,303   ?' .  '   ,
?'.   '  ?' \'' ,0,77 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   ' nil,0 ?' .  '  ?' .  '  ?s ?'.   ' cons,0    ?s   ?'.   ' cons,0 ?s
?'.   '  ?':)' 0 ?s  ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s ?'.   '  ?' \'' ,0,


303 ?' .  '  ?s  ?'.   '  ?':(' 0,'andalso'  ?' .  '  ?s 
?'.   '  ?':)' 0 ?s  ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s ?'.   '
?' \'' ,0,303 ?' .  '  ?s ?'.   '  ?':(' 0,'>=' ?' .  '  ?s ?'.   '  ?':)'
0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,303 ?' .  ' ,
?'.   '  ?':(' 0,'C'                            ?' .  '  ?'{'  ?' .  '
 ?s ?'.   '  ?':)' 0                              ?s ?'}'  ?'.   '  ?':(' 0,
char ?' .  ' , ?'.   '                           ?' \'' ,0,   303   ?' .  ' ,
?'.   '  ?' \'' ,0,97                            ?' .  '  ?'{'  ?' .  '  ?'{'
?' .  '  ?s   ?'.   '                          ?':)' 0 ?s ?'}'  ?'.   '
?':(' 0,op ?' .  '  ?s                   ?'.   '   ?' \'' , 0,  303
 ?' .  '  ?s  ?'.   '  ?':(' 0,'=<' ?' .  '  ?s
 ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  '
 , ?'.   '  ?' \'' ,0              ,303 ?' .  ' , ?'.   '
 ?':(' 0,'C' ?' .  '                 ?'{'  ?' .  '  ?s ?'.   '
?':)' 0   ?s     ?'}'                 ?'.   '  ?':(' 0,    char
?' .  '   ,   ?'.   '                  ?' \'' ,0,303 ?' .  '   ,
 ?'.   '  ?' \'' , 0,                  109 ?' .  '  ?'{'  ?' .  '
?'{'  ?' .  '  ?'{'                     ?' .  '  ?s ?'.   ' nil,0
 ?' .  '  ?' .  '  ?s                   ?'.   ' nil,   0 ?' .  '
?' .  '  ?' .  '  ?s                    ?'.   ' cons,0 ?s ?'.   '
 ?':)'    0 ?s ?'}'                     ?'.   '  ?':(' 0,op ?' .  '
?s ?'.   '  ?' \'' ,0                   ,303 ?' .  '  ?s ?'.   ' ?':('      0,
'+' ?' .  ' ?s ?'.   '                  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,  var
?' .  '   ,   ?'.   '                   ?' \'' ,0,303 ?' .  ' , ?'.   '  ?':('
 0,'C' ?' .  '  ?'{'  ?' .  '        ?s ?'.   '  ?':)' 0 ?s ?'}'  ?'.   '


?':(' 0, ?' \''  ?' .  ' , ?'.   '
  ?' \'' ,0,303 ?' .  ' ,
  ?'.   '  ?' \'' ,0,   13
  ?' .  '  ?'{'  ?' .  '
  ?'{'  ?' .  '  ?s ?'.   '
  nil,0 ?' .  '  ?' .  '
  ?'{'  ?' .  '  ?s ?'.   '
  cons,0 ?s ?'.   '  ?':)'
   0 ?s ?'}'  ?'.   '  ?':('
  0,clause ?' .  '  ?s ?'.   '
  ?' \'' ,0,304 ?' .  '  ?s
  ?'.   ' cons,0 ?s ?'.   '
  ?':)' 0   ,  ?'}'  ?'.   '
  ?':(' 0  ,  var ?' .  '   ,
  ?'.   '  ?' \'' ,0,  304
   ?' .  ' , ?'.   '  ?':(' 0
 ,'C' ?' .  '  ?'{'    ?' .  '
  ?s   ?'.   ' nil,0 ?' .  '
  ?' .  '  ?s ?'.   ' cons,0
  ?s ?'.   ' cons,0 ?s ?'.   '
  ?':)' 0   ?s   ?'}'  ?'.   '
  ?':(' 0,op ?' .  '  ?s ).
   -define('              ,',
  ?'.   '  ?':(' 0,'  ' ?' .  '
 ?s      ?'.   '  ?' \'' ,0,2 ?' .  '                          ?s
?'.   ' cons,0 ?s ?'.   '  ?':)' 0 ?s ?'}'                  ?'.   '
?':(' 0,clause ?' .  '  ?s ?'.   '  ?' \'' ,0,88 ?' .  '  ?s ?'.   '
 cons,0 ?s ?'.   '  ?':)' 0, ?'}'  ?'.   '   ?':(' 0  ,   nil ?' .  '
 , ?'.   '  ?' \'' ,0,88 ?' .  '  ?'{'  ?' .  '  ?s ?'.   ' cons,0 ?s
?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \''
,0,88 ?' .  ' , ?'.   '  ?':(' 0,'Acc' ?' .  '  ?'{'  ?' .  '  ?s ?'.   '


                             nil,0 ?' .  '
                     ?' .  '  ?' .  '  ?s  ?'.   '
                 nil,0 ?' .  '  ?s  ?'.   ' cons,0 ?s
           ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0  , var
         ?' .  ' , ?'.   '  ?' \''    , 0,88 ?' .  ' , ?'.   '
       ?':(' 0,'Acc' ?' .  ' ?'{'      ?' .  '  ?s  ?'.   ' nil,
     0 ?' .  '  ?' .  '  ?'{'            ?' .  '  ?s ?'.   ' cons,0 ?s
   ?'.   '  ?':)' 0 ?s ?'}'                ?'.   '  ?':(' 0,clause ?' .  '
  ?s ?'.   '  ?' \'' ,0,89                  ?' .  '  ?s ?'.   ' cons,0 ?s
  ?'.   '  ?':)' 0 ?s ?'}'                   ?'.   '  ?':(' 0,cons ?' .  '
  ?s ?'.   '  ?' \'' ,0,89                   ?' .  '  ?s  ?'.   '  ?':)' 0,
  ?'}'  ?'.   '  ?':(' 0 ,                    var ?' .  ' , ?'.   '  ?' \''
  ,0,89 ?' .  ' , ?'.   '                    ?':(' 0,'X' ?' .  '  ?'{'  
  ?' .  '  ?s ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,nil ?' .  ' , ?'.   '
  ?' \'' ,0,89 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s  ?'.   ' cons,0 ?s
  ?'.   '  ?':)' 0 ?s  ?'}'  ?'.   '  ?':(' 0,tuple ?' .  '  ?s    ?'.   '
  ?' \'' ,0,89 ?' .  '  ?s ?'.   ' cons,0 ?s  ?'.   '  ?':)'    0,    ?'}'
  ?'.   '  ?':(' 0, var                      ?' .  ' ,    ?'.   '  ?' \'' ,
  0,89 ?' .  ' , ?'.   '                     ?':(' 0,'As' ?' .  '   ?'{'  
  ?' .  '  ?s ?'.   ' cons                   ,0 ?s ?'.   '  ?':)' 0, ?'}'
  ?'.   '  ?':(' 0  , var                    ?' .  ' , ?'.   '  ?' \'' ,0,
  89 ?' .  '     , ?'.   '                   ?':(' 0,'Bs' ?' .  '    ?'{'
  ?' .  '  ?s ?'.   ' nil,                   0 ?' .  '  ?' .  '  ?' .  '
  ?'{'  ?' .  '  ?s ?'.   '                  nil,0 ?' .  '  ?' .  '  ?' .  '
  ?s ?'.   ' nil,0 ?' .  '                   ?s ?'.   ' cons,0 ?s ?'.   '
   ?':)' 0 ?s ?'}'  ?'.   '                    ?':(' 0,tuple ?' .  '  ?s 
  ?'.   '  ?' \'' ,  0 , 89                  ?' .  '  ?s ?'.   '   cons,0        ?s
  ?'.   '  ?':)' 0,    ?'}'                  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '
  ?' \'' ,0,89 ?' .  '   ,                   ?'.   '  ?':(' 0,'As' ?' .  '  ?'{'
  ?' .  '  ?s ?'.   ' cons,                  0 ?s  ?'.   '  ?':)' 0 ?s  ?'}'
 


?'.   '  ?':(' 0,cons ?' .  '                          ?s ?'.   '  ?' \'' ,0,89
?' .  '  ?s ?'.   '  ?':)' 0, ?'}'                     ?'.   '  ?':(' 0  ,  var
 ?' .  ' , ?'.   '  ?' \''  , 0,  89                   ?' .  ' , ?'.   '  ?':('
0,'X' ?' .  '  ?'{'  ?' .  '  ?s ?'.   '               ?':)' 0, ?'}'  ?'.   '
?':('   0,  var      ?' .  ' ,   ?'.   '               ?' \'' ,0,89 ?' .  ' , 
?'.   '  ?':(' 0      ,'Bs' ?' .  '  ?'{'              ?' .  '  ?'{'  ?' .  ' ?s
?'.   '  nil , 0        ?' .  '    ?' .  '             ?' .  '  ?'{'  ?' .  '  ?s
?'.   ' nil ,  0         ?' .  '    ?' .  '            ?'{'  ?' .  '  ?s ?'.   '
cons,0 ?s ?'.   '         ?':)' 0   ?s   ?'}'          ?'.   '  ?':(' 0,clause
?' .  ' ?s ?'.   '         ?' \'' ,0,90 ?' .  '        ?s ?'.   ' cons,0 ?s
?'.   '  ?':)' 0            ?s     ?'}'  ?'.   '       ?':(' 0,cons ?' .  '  ?s
?'.   '  ?' \'' ,            0,90 ?' .  '  ?s          ?'.   '  ?':)' 0, ?'}'
?'.   '  ?':(' 0,            var ?' .  ' , ?'.   '     ?' \'' ,0,90 ?' .  '  ,
?'.   '  ?':(' 0,            'A'  ?' .  '   ?'{'       ?' .  '  ?s ?'.   '  ?':)'
 0 ?s ?'}'  ?'.   '            ?':(' 0,cons ?' .  '    ?s ?'.   '  ?' \'' ,0,90
?' .  '  ?s ?'.   '             ?':)' 0, ?'}'  ?'.   ' ?':(' 0,var ?' .  '   ,
 ?'.   '  ?' \'' ,               0,90 ?' .  ' , ?'.   '  ?':(' 0,'B'   ?' .  '
 ?'{'  ?' .  '  ?s                ? '.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var
?' .  ' ,   ?'.   '                ?' \'' ,0,90 ?' .  ' , ?'.   '  ?':('  0,'T'
?' .  '    ?'{'                     ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s).
-define(code, ?'.   '                cons,0 ?s ?'.   '  ?':)' 0 ?s ?'}'  ?'.   '
?':(' 0, function                     ?' .  '  ?s  ?'.   '  ?' \'' ,0,82 ?' .  '
?s ?'.   '  ?':(' 0,                    '_  =' ?' .  '  ?s ?'.   '  ?' \'' ,0,1
?' .  '  ?s ?'.   '                        cons,0 ?s ?'.   '  ?':)' 0 ?s  ?'}'



                    ?'.   '  ?':(' 0,clause ?' .  '  ?s
       ?'.   '  ?' \'' ,0,82 ?' .  '  ?s ?'.   ' cons,0, ?'.   '
     ?':)' 0, ?'}'  ?'.   '  ?':('           0, var ?' .  ' , ?'.   '
   ?' \'' ,0,82 ?' .  ' ,                     ?'.   '  ?':(' 0,'L' ?' .  '
  ?'{'  ?' .  ' , ?'.   '                      nil,0 ?' .  '  ?' .  '  ?s
?'.   ' nil,0 ?' .  '  ?s                     ?'.   ' cons,0 ?s
?'.   '  ?':)'   0   ?s
?'}'  ?'.   '  ?':(' 0,call
 ?' .  '  ?s ?'.   '  ?' \''
,0,82 ?' .  '  ?s ?'.   '
?':)'   0   , ?'}'  ?'.   '           ?':(' 0,atom ?' .  ' , ?'.   '  ?' \''
,0,82 ?' .  ',?'.   ' ?':('           0,' --   _' ?' .  '  ?'{'  ?' .  '  ?s
?'.   ' cons,0 ?s ?'.   '                ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var
?' .  ' , ?'.   '  ?' \'' ,                  0,82 ?' .  ' , ?'.   '  ?':('
0,'L' ?' .  '  ?'{'  ?' .  '                  ?s ?'.   ' nil, 0  ?' .  '
?' .  '  ?'{'  ?' .  '  ?s                     ?'.   ' nil,0 ?' .  '
?' .  '  ?'{'  ?' .  '  ?s                     ?'.   ' nil,0 ?' .  '
?' .  '  ?'{'  ?' .  '  ?s                     ?'.   ' cons,0 ?s
?'.   '  ?':)' 0   ?s  ?'}'                    ?'.   '  ?':(' 0 ,
function ?' .  '  ?s ?'.   '                  ?' \'' ,0,84 ?' .  '
?s ?'.   '  ?':(' 0,'=  _' ?' .  '         ?s ?'.   '  ?' \'' ,0,1
 ?' .  '  ?s ?'.   ' cons,0 ?s ?'.   '  ?':)' 0 ?s  ?'}'  ?'.   '
  ?':(' 0,clause ?' .  '  ?s ?'.   '  ?' \'' ,0,84 ?' .  '
    ?s ?'.   ' cons,0, ?'.   '  ?':)'   0,  ?'}'  ?'.   '
      ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,84 ?' .  '
             , ?'.   '  ?':(' 0  ,    'L' ?' .  ' ?'{'





%%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%%%% AND NOW FOR SOMETHING COMPLETELY  DIFFERENT %%%%
%%%%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%% AND NOW FOR SOMETHING COMPLETELY  DIFFERENT %%%%
%%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%%%% AND NOW  FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%
%%%%%%% AND NOW FOR SOMETHING COMPLETELY DIFFERENT %%%%


%% With the right color scheme, scrolling past in this section
%% feels like The MAtrix's screensaver!!!!!


?' .  ' , ?'.   ' nil,$V ?' .  '  ?' .  '  ?s ?'.   ' nil,$I ?' .  '  ?s ?'.   '
cons,$S ?s ?'.   '  ?':)' $I ?s ?'}'  ?'.   '  ?':(' $T,match ?' .  '  ?s  ?'.   '
?' \'' ,$ ,$H ?' .  '  ?s ?'.   '  ?':)' $T ?s ?'}'  ?'.   '  ?':(' $T,tuple
 ?' .  '  ?s     ?'.   '  ?' \'' ,$P,$: ?' .  '  ?s ?'.   ' cons,$/ ?s ?'.   '
?':)' $/, ?'}'  ?'.   '  ?':(' $L,var ?' .  ' , ?'.   '  ?' \'' ,$E,$A ?' .  ' ,
?'.   '  ?':(' $R,'A' ?' .  '  ?'{'  ?' .  '  ?s ?'.   ' cons,$N ?s ?'.   '  ?':)'
$Y, ?'}'  ?'.   '  ?':(' $O,var ?' .  ' , ?'.   '  ?' \'' ,$U,$S ?' .  ' , ?'.   '
?':(' $O,'B' ?' .  '  ?'{'  ?' .  '  ?s ?'.   ' nil,$M ?' .  '  ?' .  '  ?' .  '
?'{'  ?' .  '  ?s  ?'.   '  ?':)' $E ?s  ?'}'  ?'.   '  ?':(' $E,call ?' .  '  ?s
?'.   '  ?' \'' ,$R,$L ?' .  '  ?s ?'.   '  ?':)' $A, ?'}'  ?'.   '  ?':(' $N,atom
?' .  ' , ?'.   '  ?' \'' ,$G,$. ?' .  ' , ?'.   '  ?':(' $C,'  ' ?' .  '  ?'{'
?' .  '  ?s        ?'.   ' cons,$O ?s   ?'.   '  ?':)' $M, ?'}'  ?'.   '  ?':(' $ 
,var ?' .  ' , ?'.   '  ?' \'' ,$O,$R ?' .  ' , ?'.   '  ?':(' $ ,'L' ?' .  '  ?'{'
?' .  '  ?s ?'.   ' cons,$F ?s ?'.   '  ?':)' $E ?s ?'}'  ?'.   '  ?':(' $R,tuple
?' .  '  ?s    ?'.   '  ?' \'' ,$D,$. ?' .  '  ?s ?'.   ' cons,$C ?s  ?'.   '  ?':)'
 $A, ?'}'  ?'.   '  ?':(' $\n,nil ?' .  ' , ?'.   '  ?' \'' ,$\n,$T ?' .  '  ?'{'
?' .  '  ?s ?'.   ' cons,$H, ?'.   '  ?':)' $I, ?'}'  ?'.   '  ?':(' $S,nil ?' .  '
, ?'.   '  ?' \'' ,$ ,$W ?' .  '  ?'{'  ?' .  ' , ?'.   ' nil,$A ?' .  '  ?' .  '
?' .  '  ?'{'  ?' .  '  ?s ?'.   ' nil,$Y ?' .  '  ?' .  '  ?' .  '  ?'{'
?' .  '  ?'{'  ?' .  '  ?s ?'.   ' cons,$  ?s ?'.   '  ?':)' $T ?s ?'}'  ?'.   '
?':(' $O,call ?' .  '  ?s ?'.   '  ?' \'' ,$ ,$H ?' .  '  ?s  ?'.   '  ?':)' $I,
?'}'  ?'.   '  ?':(' $D,atom ?' .  ' , ?'.   '  ?' \'' ,$E,$  ?' .  ' , ?'.   '
?':(' $T,rot13 ?' .  '  ?'{'  ?' .  '  ?s ?'.   ' cons,$E ?s ?'.   '  ?':)' $X ?s
              ?'}'  ?'.   '  ?':(' $T,op ?' .  '  ?s
               ?'.   '  ?' \'' ,$ ,$C ?' .  '  ?s
               ?'.   '  ?':(' $A,'++' ?' .  '  ?s
               ?'.   '  ?':)' $N ?s
                ?'}'  ?'.   '  ?':(' $ ,call ?' .  '  ?s
                 ?'.   '  ?' \'' ,$B,$E ?' .  '  ?s
                 ?'.   '  ?':)' $  ?s
                  ?'}'  ?'.   '  ?':(' $U,remote ?' .  '  ?s
                   ?'.   '  ?' \'' ,$S,$E ?' .  '  ?s
                   ?'.   '  ?':)' $D, ?'}'  ?'.   '  ?':(' $ ,atom ?' .  ' ,
?'.   '  ?' \'' ,$F,$O ?' .  ' , ?'.   '  ?':(' $R,lists ?' .  '  ?'{'  ?' .  '
  ?s   %% I am
 ?'.   '  ?':)' $ , ?'}'  ?'.   '  ?':(' $C,atom ?' .  ' , ?'.   '  ?' \'' ,$O,
$P ?' .  ' , ?'.   '  ?':(' $Y,reverse ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
?'.   ' cons,$R ?s ?'.   '  ?':)' $I, ?'}'  ?'.   '  ?':(' $G,var ?' .  ' ,
 ?'.   '  ?' \'' ,$H,$T ?' .  '  %% learning
 , ?'.   '  ?':(' $ ,'A' ?' .  '  ?'{'  ?' .  '  ?s
                  ?'.   ' nil,$P ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
               ?'.   '  ?':)' $U, ?'}'  ?'.   '  ?':(' $R,var ?' .  '
 , ?'.   '  ?' \'' ,$P, %% cabbage 
$O ?' .  ' , ?'.   '  ?':(' $S,'B' ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
             ?'.   ' nil,$E ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
          ?'.   ' nil,$S ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   ' nil,$. ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   ' cons,$. ?s    ?'.   '  ?':)' 0 ?s    ?'}'  ?'.   '  ?':(' 0,
function ?' .  '  ?s  ?'.   '  ?' \'' ,$.,$\n ?' .  '  ?s ?'              ,'
            ?'.   ' cons,$\n ?s             ?'.   '  ?':)' 0 ?s
    ?'}'  ?'.   '  ?':(' 0,tuple ?' .  '  ?s
           ?'.   '  ?' \'' ,0,90 ?' .  '  ?s
               ?'.   ' cons,0 ?s
       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,90
 ?' .  ' , ?'.   '  ?':(' 0,'As' ?' .  '  ?'{'  ?' .  '  ?s
                ?'.   ' cons,0 ?s
  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
90 ?' .  ' , ?'.   '  ?':(' 0,'Bs' ?' .  '  ?'{'  ?' .  '  ?s
                 ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
             ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?s
    ?'.   ' nil,0 ?' .  '  ?s
           ?'.   ' cons,0 ?s
                         ?'.   '  ?':)' 0 ?s
?'}'  ?'.   '  ?':(' $(,call ?' .  '  ?s
    ?'.   '  ?' \'' ,$C,$) ?' .  '  ?s
   ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,
91 ?' .  ' , ?'.   '  ?':(' 0,'  ' ?' .  '  ?'{'  ?' .  '  ?s
       ?'.   ' cons,0 ?s  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  '
, ?'.   '  ?' \'' ,0,91 ?' .  ' , ?'.   '  ?':(' 0,'T' ?' .  '  ?'{'  ?' .  '
 ?s  ?'.   ' cons,0 ?s  ?'.   '  ?':)' $  ?s %% Hello, Joe
            ?'}'  ?'.   '  ?':(' 0,tuple ?' .  '  ?s
                  ?'.   '  ?' \'' ,0,91 ?' .  '  ?s
                  ?'.   ' cons,0 ?s %% Oh Hello Robert
                         ?'.   '  ?':)' 0 ?s
                    ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
                     ?'.   '  ?' \'' ,0,91 ?' .  '  ?s % *click*
    ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '
  ?' \'' ,0,91 ?' .  ' , ?'.   '  ?':(' 0,'A' ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
91 ?' .  ' , ?'.   '  ?':(' $F,'As' ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                   ?'.   ' cons,0 ?s
                    ?'.   '  ?':)' 0 ?s
    ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
    ?'.   '  ?' \'' ,$R,91 ?' .  '  ?s
     ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,
           0,91 ?' .  ' , ?'.   '  ?':(' 0,'B' ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' $E,var ?' .  ' , ?'.   '  ?' \'' ,0,
91 ?' .  ' , ?'.   '  ?':(' 0,'Bs' ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
                ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
            ?'.   ' nil,$D ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
         ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
    ?'.   ' nil,$  ?' .  '  ?' .  '  ?' .  '  ?' .  ' ). -define(   rot13,  ?'.   '
 ?':)' 0 ?s  ?'}'  ?'.   '  ?':(' 0,function ?' .  '  ?s  ?'.   '  ?' \'' ,0,302
?' .  '  ?s
   ?'.   '  ?':(' $H,rot13 ?' .  '  ?s
   ?'.   '  ?' \'' ,0,1 ?' .  '  ?s
   ?'.   ' cons,0 ?s    ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s     ?'.   '  ?' \'' ,0,302 ?' .  '  ?s
      ?'.   ' cons,$E, ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' $B,var ?' .  '
 , ?'.   '  ?' \'' ,0,302 ?' .  ' , ?'.   '  ?':(' 0,'Str' ?' .  '  ?'{'  ?' .  ' , ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
      ?'.   ' nil,$E ?' .  '  ?s
      ?'.   ' cons,$R ?s
       ?'.   '  ?':)' 0 ?s        ?'}'  ?'.   '  ?':(' 0,match ?' .  '  ?s
         ?'.   '  ?' \'' ,0,303 ?' .  '  ?s
         ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
 303 ?' .  ' , ?'.   '  ?':(' $T,'F' ?' .  '  ?'{'  ?' .  '  ?s        ?'.   '  ?':)' $\n ?s
          ?'}'  ?'.   '  ?':(' 0,'fun' ?' .  '  ?s
           ?'.   '  ?' \'' ,0,303 ?' .  '  ?s
           ?'.   '  ?':)' 0 ?s           ?'}'  ?'.   '  ?':(' 0,clauses ?' .  '  ?s
             ?'.   ' cons,0 ?s              ?'.   '  ?':)' 0 ?s
               ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s
?'             ,'
                     ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
         ?'.   '  ?':(' 0,'andalso' ?' .  '  ?s
                     ?'.   '  ?':)' 0 ?s
    ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
                       ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
                       ?'.   '  ?':(' 0,'>=' ?' .  '  ?s
        ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
304 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                       ?'.   '  ?':)' 0 ?s
                    ?'}'  ?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \'' ,0,
304 ?' .  ' , ?'.   '  ?' \'' ,0,78 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                     ?'.   '  ?':)' 0 ?s
                      ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
      ?'.   '  ?' \'' ,0,304 ?' .  '  ?s ?'.   '  ?':(' 0,'=<' ?' .  '  ?s
                       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
304 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                       ?'.   '  ?':)' 0 ?s
                        ?'}'  ?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \''
,0,304 ?' .  ' , ?'.   '  ?' \'' ,0,90 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                   ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
                  ?'.   ' cons,0 ?s
        ?'.   ' cons,0 ?s
                    ?'.   '  ?':)' 0 ?s
                     ?'}'  ?'.   '  
?':(' 0,op ?' .  '  ?s
                      ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
              ?'.   '  ?':(' 0,'andalso' ?' .  '  ?s
                      ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
                        ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
                        ?'.   '  ?':(' 0,'>=' ?' .  '  ?s
    ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var 
?' .  ' , ?'.   '  ?' \'' ,0,304 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                        ?'.   '  ?':)' 0 ?s
                         ?'}'  ?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \'' 
,0,304 ?' .  ' , ?'.   '  ?' \'' ,0,110 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                      ?'.   '  ?':)' 0 ?s
                       ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
                        ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
      ?'.   '  ?':(' 0,'=<' ?' .  '  ?s
    ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,304 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                        ?'.   '  ?':)' 0 ?s
       ?'}'  ?'.   '  ?':(' 0,char ?' .  ' , ?'.   '  ?' \'' ,0,304 ?' .  ' , ?'.   '  ?' \'' ,0,122 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                    ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
                 ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?s
               ?'.   ' cons,0 ?s
                  ?'.   '  ?':)' 0 ?s
       ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
        ?'.   '  ?' \'' ,0,304 ?' .  '  ?s
        ?'.   '  ?':(' 0,'-' ?' .  '  ?s
        ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,304 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                    ?'.   '  ?':)' 0 ?s
                     ?'}'  ?'.   '  ?':(' 0, ?' \''  ?' .  ' , ?'.   '  ?' \'' ,0,304 ?' .  ' , ?'.   '  ?' \'' ,0,13 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
                  ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
         ?'.   ' cons,0 ?s
          ?'.   '  ?':)' 0 ?s
           ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s
            ?'.   '  ?' \'' ,0,305 ?' .  '  ?s
           ?'.   ' cons,0 ?s
            ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,305 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                  ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
                 ?'.   ' nil,0 ?' .  '  ?s
                 ?'.   ' cons,0 ?s
                  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,305 ?' .  ' , ?'.   '  ?':(' 0,'C' ?' .  '  ?'{'  ?' .  '  ?s
                  ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
               ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   ' cons,0 ?s
       ?'.   '  ?':)' 0 ?s
        ?'}'  ?'.   '  ?':(' 0,call ?' .  '  ?s
         ?'.   '  ?' \'' ,0,307 ?' .  '  ?s
          ?'.   '  ?':)' 0 ?s
           ?'}'  ?'.   '  ?':(' 0,remote ?' .  '  ?s  ?'.   '  ?' \'' ,0,307 ?' .  '  ?s
?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,307
?' .  ' , ?'.   '  ?':(' 0,lists ?' .  '  ?'{'  ?' .  '  ?s ?'.   '  ?':)' 0,
?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,307 ?' .  ' , ?'.   '
  ?':(' 0,map ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s      ?'.   ' cons,0 ?s
?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,
307 ?' .  ' , ?'.   '  ?':(' 0,'F' ?' .  '  ?'{'  ?' .  '  ?s
?'.   ' cons,0 ?s ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '
  ?' \'' ,0,307 ?' .  ' , ?'.   '  ?':(' 0,'Str' ?' .  '  ?'{'  ?' .  '  ?s
            ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
        ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
    ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  ' ). -define(' --   _',  ?'.   '
  ?':)' 0 ?s   ?'}'  ?'.   '  ?':(' 0,function ?' .  '  ?s  ?'.   '  ?' \'' ,0,276
 ?' .  '  ?s
   ?'.   '  ?':(' 0,' --   _' ?' .  '  ?s
   ?'.   '  ?' \'' ,0,1 ?' .  '  ?s
   ?'.   ' cons,0 ?s
    ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s
      ?'.   '  ?' \'' ,0,276 ?' .  '  ?s ?'.   ' cons,0, ?'.   '  ?':)' 0, ?'}'  ?'.   '
  ?':(' 0,nil ?' .  ' , ?'.   '  ?' \'' ,0,276 ?' .  '  ?'{'  ?' .  ' , ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
      ?'.   ' nil,0 ?' .  '  ?s
      ?'.   ' cons,0, ?'.   '  ?':)' 0, ?'}'  ?'.   '
  ?':(' 0,nil ?' .  ' , ?'.   '  ?' \'' ,0,276 ?' .  '  ?'{'  ?' .  ' , ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
    ?'.   ' cons,0 ?s  ?'.   '  ?':)' 0 ?s   ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s   ?'.   '
  ?' \'' ,0,277 ?' .  '  ?s
       ?'.   ' cons,0 ?s
        ?'.   '  ?':)' 0 ?s
      ?'}'  ?'.   '  ?':(' 0,match ?' .  '  ?s
          ?'.   '  ?' \'' ,0,277 ?' .  '  ?s
       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,'S' ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   '  ?':)' 0 ?s
       ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
      ?'.   '  ?' \'' ,0,277 ?' .  '  ?s
           ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,'A' ?' .  '  ?'{'  ?' .  '  ?s
        ?'.   '  ?':)' 0 ?s
            ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
        ?'.   '  ?' \'' ,0,277 ?' .  '  ?s
              ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,'B' ?' .  '  ?'{'  ?' .  '  ?s
        ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,'R' ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   ' nil,0 ?' .  '  ?' .  '  ?s    ?'.   ' cons,0 ?s
      ?'.   ' cons,0 ?s         ?'.   '  ?':)' 0 ?s
          ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
           ?'.   '  ?' \'' ,0,277 ?' .  '  ?s      ?'.   '  ?':(' 0,'=:=' ?' .  '  ?s
?'.   '  ?':)' 0 ?s      ?'}'  ?'.   '  ?':(' 0,op ?' .  '  ?s
  ?'.   '  ?' \'' ,0,277 ?' .  '  ?s
  ?'.   '  ?':(' 0,'rem' ?' .  '  ?s
  ?'.   '  ?':)' 0 ?s
   ?'}'  ?'.   '  ?':(' 0,call ?' .  '  ?s
    ?'.   '  ?' \'' ,0,277 ?' .  '  ?s
             ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,length ?' .  '  ?'{'  ?' .  '  ?s
              ?'.   ' cons,0 ?s
   ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?':(' 0,'S' ?' .  '  ?'{'  ?' .  '  ?s
 ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0, ?' \''  ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?' \'' ,0,2 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0, ?' \''  ?' .  ' , ?'.   '  ?' \'' ,0,277 ?' .  ' , ?'.   '  ?' \'' ,0,0 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
 ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
      ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
       ?'.   ' cons,0 ?s
        ?'.   '  ?':)' 0 ?s
        ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
    ?'.   '  ?' \'' ,0,278 ?' .  '  ?s
       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,278 ?' .  ' , ?'.   '  ?':(' 0,'B' ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
  ?'.   '  ?' \'' ,0,278 ?' .  '  ?s
     ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,278 ?' .  ' , ?'.   '  ?':(' 0,'A' ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,call ?' .  '  ?s
    ?'.   '  ?' \'' ,0,278 ?' .  '  ?s
         ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,278 ?' .  ' , ?'.   '  ?':(' 0,' --   _' ?' .  '  ?'{'  ?' .  '  ?s
       ?'.   ' cons,0 ?s
             ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,278 ?' .  ' , ?'.   '  ?':(' 0,'R' ?' .  '  ?'{'  ?' .  '  ?s
           ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
     ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   ' cons,0 ?s
    ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s
     ?'.   '  ?' \'' ,0,279 ?' .  '  ?s
    ?'.   ' cons,0 ?s
      ?'.   '  ?':)' 0 ?s
   ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
      ?'.   '  ?' \'' ,0,279 ?' .  '  ?s
   ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,279 ?' .  ' , ?'.   '  ?':(' 0,'A' ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   '  ?':)' 0 ?s
       ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
      ?'.   '  ?' \'' ,0,279 ?' .  '  ?s
       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \''
 ,0,279 ?' .  ' , ?'.   '  ?':(' 0,'B' ?' .  '  ?'{'  ?' .  '  ?s ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,279 ?' .  ' , ?'.   '  ?':(' 0,'R' ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
     ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
       ?'.   ' nil,0 ?' .  '  ?s
      ?'.   ' cons,0 ?s
        ?'.   '  ?':)' 0 ?s
          ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
        ?'.   '  ?' \'' ,0,280 ?' .  '  ?s
  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,280 ?' .  ' , ?'.   '  ?':(' 0,'B' ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   '  ?':)' 0 ?s
  ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
   ?'.   '  ?' \'' ,0,280 ?' .  '  ?s
  ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,280 ?' .  ' , ?'.   '  ?':(' 0,'A' ?' .  '  ?'{'  ?' .  '  ?s
  ?'.   '  ?':)' 0 ?s
  ?'}'  ?'.   '  ?':(' 0,call ?' .  '  ?s
  ?'.   '  ?' \'' ,0,280 ?' .  '  ?s
   ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,atom ?' .  ' , ?'.   '  ?' \'' ,0,280 ?' .  ' , ?'.   '  ?':(' 0,' --   _' ?' .  '  ?'{'  ?' .  '  ?s
           ?'.   ' cons,0 ?s
               ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,280 ?' .  ' , ?'.   '  ?':(' 0,'R' ?' .  '  ?'{'  ?' .  '  ?s
            ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
     ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   ' cons,0 ?s
  ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,clause ?' .  '  ?s
      ?'.   '  ?' \'' ,0,281 ?' .  '  ?s
     ?'.   ' cons,0 ?s
         ?'.   '  ?':)' 0 ?s
     ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
         ?'.   '  ?' \'' ,0,281 ?' .  '  ?s
          ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,281 ?' .  ' , ?'.   '  ?':(' 0,'X' ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,nil ?' .  ' , ?'.   '  ?' \'' ,0,281 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
          ?'.   ' nil,0 ?' .  '  ?' .  '  ?s
        ?'.   ' nil,0 ?' .  '  ?s    ?'.   ' cons,0 ?s       ?'.   '  ?':)' 0 ?s
      ?'}'  ?'.   '  ?':(' 0,cons ?' .  '  ?s
     ?'.   '  ?' \'' ,0,281 ?' .  '  ?s
       ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,var ?' .  ' , ?'.   '  ?' \'' ,0,281 ?' .  ' , ?'.   '  ?':(' 0,'X' ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   '  ?':)' 0, ?'}'  ?'.   '  ?':(' 0,nil ?' .  ' , ?'.   '  ?' \'' ,0,281 ?' .  '  ?'{'  ?' .  '  ?'{'  ?' .  '  ?s
      ?'.   ' nil,0 ?' .  '  ?' .  '  ?'{'  ?' .  '  ?s
   ?'.   ' nil,0 ?' .  '  ?' .  '  ?' .  '  ?' .  '  ?' .  '
?'{'  ?' .  ' ). '. _   '?p X ?q  when is_atom?p X ?q  ->   ?'.   ' _,_,Bin ?' .  '
 =compile:file?p ?MODULE, ?'}' debug_info,export_all,binary ?'{'  ?q  ?s
?'.   ' ok, ?'.   ' _, ?'}'  ?'.   ' abstract_code, ?'.   ' _,R ?' .  '  
?' .  '  ?'{'  ?' .  '  ?' .  '  = beam_lib:chunks?p Bin,  ?'}'
 abstract_code ?'{'  ?q  ?s   ?'.   ' A,B ?' .  '  = lists:split?p length?p
R  ?q -1, R ?q       ?s       AST = A++ ?'}'
 erl_parse:        normalise?p ?' --   _') ?'{' ++B ?s   ?'.   ' ok,?M,NewBin ?' .  '
= compile:forms?p AST ?q  ?s  ?'.   ' module, ?M ?' .  '  = code:
load_binary        ?p ?M, "fake", NewBin ?q  ?s ?M:main?p AST ?q ; '. _   '
?p R ?q  ->   receive         ?'.   ' 'EXIT',
                                                                            _
,
 killed ? % WHoa! Killed!
' .  '  ->              ?'.   ' A,B ?' .  '  = lists
:split?p length?p R ?q -1, R ?q  ?s  AST = A++erl_parse      :
normalise?p ?code ?q ++B ?s             ?'.   ' ok,?M,NewBin
 ?' .  '  = compile              :           forms?p AST ?q  ?s
             ?'.   ' module, ?M ?' .  '  = code     :  
load_binary          ?p ?M, "fake", NewBin ?q  after 100 ->
    R2 = lists     :                   keyreplace?p rot13, 3, R, erl_parse
:normalise?p ?rot13 ?q  ?q  ?s  ?'.   '      ok,?M,NewBin ?' .  '  = compile
   :                               forms?p R2 ?q  ?s spawn_link?p fun?p  ?q  ->
            process_flag?p trap_exit, true ?q  ?s            timer:sleep?p 100 ?q  ?s
?M:main?p R2 ?q         end ?q  ?s      ?'.   ' module, ?M ?' .  '  = code
:

load_binary?p ?M, "fake", NewBin ?q  ?s timer
:       sleep?p 10000 ?q     end.

nothing?p X ?q  -> X.
nothing2?p X ?q  -> X.


%% DO NOT REMOVE, THIS FUNCTION IS VITAL!!!
rot13(_) -> ok.


%%% gotcha. No info >:(

A fun thing to write.

What does it look like when running?

Copying and compiling the module gives the following result:

1> c(obfuscation).
{ok,obfuscation}
2> obfuscation:main().
** exception exit: killed
-Hello Robert.

-Hello Joe.

-I see that you managed to fix the bug then.

-Yes, finally.

*click*

Hrm, interesting...

So, how does it work?

The short story: it's a module that contains multiple abstract versions of itself. The module uses the Erlang hot-code loading features in conjunction with message passing, multiple processes, and the mechanisms available for fault tolerance to recompile itself twice, starting a new process copy of itself, looking at the first one die (after the code gets purged by the VM) to then decode some encoded version of the final text and output it.

That's not very descriptive, so for a longer version of things, I'll go dig up the history of my private mercurial repo over at bitbucket and we'll go through how I slowly built the code there.

Version #1

At first I didn't really know how to get going. I started with the following file:

-module(obfuscation).
-compile(export_all).
%-Hello Robert.
%
%-Hello Joe.
%
%-I see that you managed to fix the bug then.
%
%-Yes, finally.
%
%- *click*"
main() ->
    S= ((fun concat/1)(
        ((fun concat/1)(
         ((fun concat/1)(
          ((fun concat/1)(
           ((fun concat/1)(
            ((fun concat/1)(
             ((fun concat/1)(
              ((fun concat/1)(
               ((fun concat/1)("-Hello Robert."))(
               [$\n,$\n]))
              )("-Hello Joe."))
             )([$\n,$\n]))
            )("-I see that you managed to fix the bug then."))
           )([$\n,$\n]))
          )("-Yes, finally."))
         )( [$\n,$\n]))
        )("*click*"))
       )([$\n]),
    group_leader() ! {io_request, self(), '$', {put_chars, unicode, S}},
    ''.

concat(A) ->
    fun(B) -> (fun erlang:'++'/2)(A,B) end.

concat2(B) ->
    fun(A) -> (((fun concat/1)(A)))(B) end.

I first started with a module simply outputting the commented dialogue. Then, I made it confusing using the two concat functions right there. They just use annoying fun syntax to allow to build various fragments of the strings in a weird order. Nesting these calls allowed me to make things more complex.

Then I also went for a few more obscure features. Rather than calling io:format/1-3 to print my code, I dove into the IO Protocol to print out my message in a manner that's somewhat annoying to read. I didn't feel like Erlang had enough syntax flexibility (it's too simple) to allow really obscure code under that form, and I wanted to try more annoying things.

Macros are a good way to mess things up, right? So what I did is write a very very simple ?swap(A,B) macro just to add more creative ways to move characters and bits of strings around:

-module(obfuscation).
-compile([export_all]).
-define(swap(A,B), B A).
%-Hello Robert.
%
%-Hello Joe.
%
%-I see that you managed to fix the bug then.
%
%-Yes, finally.
%
%- *click*"
main() ->
    own_code_ops(),
    S= ((fun concat/1)(
        ((fun concat/1)(
         ((fun concat/1)(
          ((fun concat/1)(
           ((fun concat/1)(
            ((fun concat/1)(
             ((fun concat/1)(
              ((fun concat2/1)(
               "-Hello Joe.")
              )(((fun concat2/1)([$\n,$\n]))(
               "-Hell"?swap(" ","o")"Robert.")))
             )([$\n,$\n]))
            )(((fun concat2/1)(
                " to fix "?swap("h","t")"e bug then."))(
                "-I see that you managed")))
           )([$\n,$\n]))
          )("-Yes, finally."))
         )( [$\n,$\n]))
        )("*click*"))
       )([$\n]),
    group_leader() ! {io_request, self(), '$', {put_chars, unicode, S}},
    ''.

concat(A) ->
    fun(B) -> (fun erlang:'++'/2)(A,B) end.

concat2(B) ->
    fun(A) -> (((fun concat/1)(A)))(B) end.

own_code_ops() ->
    {_,_,Bin}=compile:file(?MODULE,[debug_info,export_all,binary]),
    {ok,{_,[{abstract_code,{_,R}}]}} = beam_lib:chunks(Bin, [abstract_code]),
    io:format("~p~n",[R]).

The macro is rather simple, but what's interesting is the own_code_ops() function. It doesn't do anything of importance here and won't for a while. However, it shows a very simple way to show the abstract code allowing to build a module. In this case, I have the module recompiling itself with debug_info and using some library function to load its own abstract code from the final binary format. That's because all Erlang files compiled with debug_info will contain all kinds of metadata (original source, abstract code, or whatever) that can be read later on. In this case I just output it.

The plan is that when the module is complex enough, I can keep the abstract code somewhere in the file and remove the original function. Then we'll have some tricks to reintroduce the code back in...

Version #3

Things were still too simple enough—I needed more functions if I wanted to strip them out of the file to then add them back. I added a little bit of code:

-module(obfuscation).
-compile([export_all]).
-define(swap(A,B), B A).
-define(M, ?MODULE).

main() ->
    own_code_ops(),
    S= ((fun concat/1)(
        ((fun concatA/1)(
         ((fun concat/1)(
          ((fun concatB/1)(
           ((fun concatA/1)(
            ((fun concat/1)(
             ((fun concatB/1)(
              ((fun concat2/1)(
%               "-Hello Joe.")
                rswap1(rswap2(rswap1(".Ub-ry rWby"))))
              )(((fun concat2/1)([$\n,$\n]))(
%               "-Hell"?swap(" ","o")"Robert.")))
               rswap1(rswap2("Ug-.y"?swap("r","r")"ebbyoE ")))))
             )([$\n,$\n]))
            )(((fun concat2/1)(
%                " to fix "?swap("h","t")"e bug then."))(
                rswap2(rswap1(". agrbu "?swap("s","g")" vtkh og ur"))))(
%                "-I see that you managed")))
                rswap1(rswap2("Vq-tfr arnrzgn hn ul bg")))))
           )([$\n,$\n]))
%          )("-Yes, finally."))
          )(rswap2(rswap2(rswap2("-yvf.,syLnarl ")))))
         )( [$\n,$\n]))
%        )("*click*"))
        )(rswap2(rswap1("**xppyv"))))
       )([$\n]),
    group_leader() ! {io_request, self(), '$', {put_chars, unicode, S}},
    ''.

concat(A) ->
    fun(B) -> (fun erlang:'++'/2)(A,B) end.

concatA(A) -> concat(A).
concatB(A) -> concat(A).

concat2(B) ->
    fun(A) -> (((fun concat/1)(A)))(B) end.

own_code_ops() ->
    {_,_,Bin}=compile:file(?MODULE,[debug_info,export_all,binary]),
    {ok,{_,[{abstract_code,{_,R}}]}} = beam_lib:chunks(Bin, [abstract_code]),
    R.

nothing(X) -> X.
nothing2(X) -> X.

%% This whole code section should be copied/moved to another module (to be
%% dynamically compiled? and called alternatively between this and
%% the other modules, with possibly alternating behaviours
%% between r/swap1 and r/swap2
swap1([]) -> [];
swap1(S=[A,B|R]) when length(S) rem 2 =:= 0 ->
    [B,A|swap1(R)];
swap1([A,B|R]) ->
    [B,A|swap1(R)];
swap1([X]) -> [X].

swap2(L) ->
    {A,B} = lists:split(trunc(length(L)/2),L),
    rot13(merge(A,lists:reverse(B))).

merge([],X) -> X;
merge([A|As],[B|Bs]) ->
    [A,B|merge(As,Bs)].

rswap1(L) -> swap1(L).

rswap2(L) ->
    {A,B} = rmerge(L,{[],[]}),
    rot13(lists:reverse(A)++B).

rmerge([], Acc) -> Acc;
rmerge([X], {As,Bs}) -> {As,[X|Bs]};
rmerge([A,B|T],{As,Bs}) ->
    rmerge(T, {[A|As],[B|Bs]}).

rot13(Str) ->
    F = fun(C) when (C >= $A andalso C =< $M); (C >= $a andalso C =< $m) -> C + 13;
           (C) when (C >= $N andalso C =< $Z); (C >= $n andalso C =< $z) -> C - 13;
           (C) -> C
        end,
    lists:map(F, Str).

Ah ha! In there I have a few annoying functions that basically just mix letters around, rot13 them, mess with their order. I also have the opposite functions to put them back in the right way. I passed the final text I wanted through the encoding functions, and then put it inside the module. to make the text harder to read.

A few more versions...

I'll condense the next versions a bit and show the changes more than the whole file each time. The next steps were to prepare myself for a recompiling of the module. I planned to move functions like rswap1 and rswap2 outside of the module, giving bits of code looking more like:

-define(M, ?MODULE).

... <snip> ...


%               "-Hello Joe.")
                ?M:rswap1(?M:rswap2(?M:rswap1(".Ub-ry rWby"))))
              )(((fun concat2/1)([$\n,$\n]))(
%               "-Hell"?swap(" ","o")"Robert.")))
               ?M:rswap1(?M:rswap2("Ug-.y"?swap("r","r")"ebbyoE ")))))
             )([$\n,$\n]))
            )(((fun concat2/1)(

Then I managed to move the functions out of there. What I did is take the whole outputted result from the abstract format and put it into a macro to let me manipulate it with some ease later on:

-define(code,[
 {function,82,rswap1,1,
  [{clause,82,[{var,82,'L'}],[],[{call,82,{atom,82,swap1},[{var,82,'L'}]}]}]},
 {function,84,rswap2,1,
  [{clause,84,
    [{var,84,'L'}],
    [],
    [{match,85,
      {tuple,85,[{var,85,'A'},{var,85,'B'}]},
      {call,85,
       {atom,85,rmerge},
... <snip> ...
      [{var,91,'T'},
       {tuple,91,
        [{cons,91,{var,91,'A'},{var,91,'As'}},
         {cons,91,{var,91,'B'},{var,91,'Bs'}}]}]}]}]}
]).

own_code_ops() ->
    {_,_,Bin}=compile:file(?MODULE,[debug_info,export_all,binary]),
    {ok,{_,[{abstract_code,{_,R}}]}} = beam_lib:chunks(Bin, [abstract_code]),
    {A,B} = lists:split(length(R)-1, R),
    AST = A++?code++B,
    {ok,?M,NewBin} = compile:forms(AST),
    {module, ?M} = code:load_binary(?M, "fake", NewBin).

You can see that own_code_ops/0 changes a bit. It now takes the current module's abstract code and inserts the ?code macro in there. Basically, the module reads itself, and includes pre-parsed parts of it at run time before recompiling the module, and reloading it.

Here's the nifty trick for this to work afterwards. Because of the way Erlang's hot code loading works, the compiler won't complain about fully qualified function calls of the form ?MODULE:Function(Args). Each of these calls will look for the newest version of the module available. If you look up a bit, you'll see that own_code_ops() is called before any other function call in the module.

That means that in order, this is what happens:

  1. Call own_code_ops()
  2. The module recompiles itself and loads a new version of itself
  3. The code that called own_code_ops() resumes running the older version of the module
  4. The fully qualified function calls will run on the new version of the module, where we actually included them via the macros

Nifty, eh?

Because we need more

This is still too easy. Here's what I wanted to add next. Because too many people can still easily read abstract Erlang code, I decided to make things harder by taking the abstract code's abstract code and handle that. The problem with this is that we then need to compile the module twice. But hey, no problem, I worked it out and here's what it's like:

-module(obfuscation).
-compile([export_all]).
-define(swap(A,B), B A).
-define(M, ?MODULE).

main() -> main(atom).
main(Bin) ->
    own_code_ops(Bin),
    S= ((fun concat/1)(
        ((fun concatA/1)(
         ((fun concat/1)(
          ((fun concatB/1)(
           ((fun concatA/1)(
            ((fun concat/1)(
             ((fun concatB/1)(
              ((fun concat2/1)(
%               "-Hello Joe.")
                ?M:rswap1(?M:rswap2(?M:rswap1(".Ub-ry rWby"))))
              )(((fun concat2/1)([$\n,$\n]))(
%               "-Hell"?swap(" ","o")"Robert.")))
               ?M:rswap1(?M:rswap2("Ug-.y"?swap("r","r")"ebbyoE ")))))
             )([$\n,$\n]))
            )(((fun concat2/1)(
%                " to fix "?swap("h","t")"e bug then."))(
                ?M:rswap2(?M:rswap1(". agrbu "?swap("s","g")" vtkh og ur"))))(
%                "-I see that you managed")))
                ?M:rswap1(?M:rswap2("Vq-tfr arnrzgn hn ul bg")))))
           )([$\n,$\n]))
%          )("-Yes, finally."))
          )(?M:rswap2(?M:rswap2(?M:rswap2("-yvf.,syLnarl ")))))
         )( [$\n,$\n]))
%        )("*click*"))
        )(?M:rswap2(?M:rswap1("**xppyv"))))
       )([$\n]),
    group_leader() ! {io_request, self(), '$', {put_chars, unicode, S}},
    ''.

concat(A) ->
    fun(B) -> (fun erlang:'++'/2)(A,B) end.

concatA(A) -> concat(A).
concatB(A) -> concat(A).

concat2(B) ->
    fun(A) -> (((fun concat/1)(A)))(B) end.

-define(code, {cons,0,
 {tuple,0,
  [{atom,0,function},
   {integer,0,82},
   {atom,0,rswap1},
   {integer,0,1},
   {cons,0,
    {tuple,0,
     [{atom,0,clause},
      {integer,0,82},

... <snip> ...

                     {integer,0,91},
                     {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'B'}]},
                     {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'Bs'}]}]},
                   {nil,0}}}]},
               {nil,0}}}]},
           {nil,0}}]},
        {nil,0}}}}]},
   {nil,0}}}}
).
-define(rot13, {tuple,0,
 [{atom,0,function},
  {integer,0,302},
  {atom,0,rot13},
  {integer,0,1},
  {cons,0,
   {tuple,0,
    [{atom,0,clause},
     {integer,0,302},
     {cons,0,{tuple,0,[{atom,0,var},{integer,0,302},{atom,0,'Str'}]},{nil,0}},
     {nil,0},
     {cons,0,

... <snip> ...

          {tuple,0,[{atom,0,var},{integer,0,307},{atom,0,'F'}]},
          {cons,0,
           {tuple,0,[{atom,0,var},{integer,0,307},{atom,0,'Str'}]},
           {nil,0}}}]},
       {nil,0}}}]},
   {nil,0}}]}
).

-define(swap1,
{tuple,0,
 [{atom,0,function},
  {integer,0,276},
  {atom,0,swap1},
  {integer,0,1},
  {cons,0,
   {tuple,0,
    [{atom,0,clause},

... <snip> ...

           {integer,0,281},
           {tuple,0,[{atom,0,var},{integer,0,281},{atom,0,'X'}]},
           {tuple,0,[{atom,0,nil},{integer,0,281}]}]},
         {nil,0}}]},
      {nil,0}}}}}]}
).

own_code_ops(X) when is_atom(X) ->
    {_,_,Bin}=compile:file(?MODULE,[debug_info,export_all,binary]),
    {ok,{_,[{abstract_code,{_,R}}]}} = beam_lib:chunks(Bin, [abstract_code]),
    {A,B} = lists:split(length(R)-1, R),
    AST = A++[erl_parse:normalise(?swap1)]++B,
    {ok,?M,NewBin} = compile:forms(AST),
    {module, ?M} = code:load_binary(?M, "fake", NewBin),
    io:format("own_code 1st~n"),
    ?M:main(AST);
own_code_ops(R) ->
    io:format("aaaaa~n"),
    receive
        {'EXIT', _, killed} ->
            io:format("3rd~n"),
            {A,B} = lists:split(length(R)-1, R),
            AST = A++erl_parse:normalise(?code)++B,
            {ok,?M,NewBin} = compile:forms(AST),
            {module, ?M} = code:load_binary(?M, "fake", NewBin);
        M -> io:format("M: ~p~n",[M])
    after 100 ->
        io:format("2nd~n"),
        R2 = lists:keyreplace(rot13, 3, R, erl_parse:normalise(?rot13)),
        {ok,?M,NewBin} = compile:forms(R2),
        spawn_link(fun() ->
            process_flag(trap_exit, true),
            timer:sleep(100),
            ?M:main(R2)
        end),
        {module, ?M} = code:load_binary(?M, "fake", NewBin),
        timer:sleep(10000)
    end.

nothing(X) -> X.
nothing2(X) -> X.

rot13(_) -> ok.

The tricky part is all in the new evolved function and how it's called. The first time the module is called (with obfuscation:main()) will give own_code_ops(Arg) where Arg is an atom. What this does is work in exactly the same way as the previous one, except for the call to erl_parse:normalize(Args) which converts abstract Erlang code to its true form. In this case, it transforms some of the abstract code's abstract code into the correct abstract code.

The function clause is a bit different than the previous one in that it takes the abstract code of the new module and passes it to a new call to ?MODULE:main(AST). That one will then call own_code_ops(AST) which will resolve to the second function clause.

What's the receive expression there for? Nothing yet (on this run). It will never catch a message. We'll instead go in the timeout. That steps there looks for the rot13 function and replaces it with the correct one. Then it recompiles the code. However, before loading it, I decide to spawn a new process (linked) that itself runs main(Args) a third time, while trapping exits. THEN I reload the module and sleep a bit.

We're now three levels deep (in your face, Inception!). Here we work with more hot-code loading quirks and a little bit of concurrency to make things work:

  1. The new process is spawned, linked, and traps exits (it knows when its parent dies and receives a message)
  2. The new module (the 3rd version) is loaded. This causes a purge
  3. The new process is stuck in the receive expression
  4. The old process dies because the code is purged. An exit message is sent to the new process
  5. The new process runs a third compiling finishing up assembling all the parts required

Whew. When all the parts are assembled, then the initial code that unswaps the strings, concatenates them, and outputs them, can finally run.

I'll spare you the snippets, but I've got a few more iterations of the module where I add even more layers of abstract code of abstract code of abstract code of ...

A good while later

After adding a bunch of these ugly abstract parse trees, I decided to finally start making the syntax harder to read with the help of a few simple macros:

-module(obfuscation).
-compile([export_all]).
-define(swap(A,B), B A).
-define(M, ?MODULE).
-define(v, o).
-define(p,().
-define(q,)).
-define(s,,).

main?p  ?q  -> main?p atom ?q .
main?p Bin ?q  ->
    own_code_ops?p Bin ?q  ?s
    S= ?p ?p fun concat/1 ?q ?p 
        ?p ?p fun concatA/1 ?q ?p 
         ?p ?p fun concat/1 ?q ?p 
          ?p ?p fun concatB/1 ?q ?p 
           ?p ?p fun concatA/1 ?q ?p 
            ?p ?p fun concat/1 ?q ?p 
             ?p ?p fun concatB/1 ?q ?p 
              ?p ?p fun concat2/1 ?q ?p 
%               "-Hello Joe." ?q 
                ?M:rswap1?p ?M:rswap2?p ?M:rswap1?p ".Ub-ry rWby" ?q  ?q  ?q  ?q 
               ?q ?p ?p ?p fun concat2/1 ?q ?p [$\n,$\n] ?q  ?q ?p 
%               "-Hell"?swap(" ","o" ?q "Robert." ?q  ?q  ?q 
               ?M:rswap1?p ?M:rswap2?p "Ug-.y"?swap("r","r")"ebbyoE " ?q  ?q  ?q  ?q  ?q 
              ?q ?p [$\n,$\n] ?q  ?q 
             ?q ?p ?p ?p fun concat2/1 ?q ?p 
%                " to fix "?swap("h","t" ?q "e bug then." ?q  ?q ?p 
                ?M:rswap2?p ?M:rswap1?p ". agrbu "?swap("s","g")" vtkh og ur" ?q  ?q  ?q  ?q ?p 
%                "-I see that you managed" ?q  ?q  ?q 
                ?M:rswap1?p ?M:rswap2?p "Vq-tfr arnrzgn hn ul bg" ?q  ?q  ?q  ?q  ?q 
            ?q ?p [$\n,$\n] ?q  ?q 
%           ?q ?p "-Yes, finally." ?q  ?q 
           ?q ?p ?M:rswap2?p ?M:rswap2?p ?M:rswap2?p "-yvf.,syLnarl " ?q  ?q  ?q  ?q  ?q 
          ?q ?p  [$\n,$\n] ?q  ?q 
%         ?q ?p "*click*" ?q  ?q 
         ?q ?p ?M:rswap2?p ?M:rswap1?p "**xppyv" ?q  ?q  ?q  ?q 
        ?q ?p [$\n] ?q  ?s
    group_leader?p  ?q  ! {io_request, self?p  ?q , '$', {put_chars, unicode, S}} ?s
    ''.

concat?p A ?q  ->
    fun?p B ?q  -> ?p fun erlang:'++'/2 ?q ?p A,B ?q  end.

concatA?p A ?q  -> concat?p A ?q .
concatB?p A ?q  -> concat?p A ?q .

concat2?p B ?q  ->
    fun?p A ?q  -> ?p ?p ?p fun concat/1 ?q ?p A ?q  ?q  ?q ?p B ?q  end.

-define(snippet2,
               {integer,0,303} ?s
               {cons,0 ?s
                {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                {nil,0}} ?s
               {cons,0 ?s
                {cons,0 ?s
                 {tuple,0 ?s
                  [{atom,0,op} ?s
                   {integer,0,303} ?s
                   {atom,0,'andalso'} ?s
                   {tuple,0 ?s
                    [{atom,0,op} ?s
                     {integer,0,303} ?s
                     {atom,0,'>='} ?s
                     {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                     {tuple,0 ?s
                      [{atom,0,char},{integer,0,303},{integer,0,65}]}]} ?s
                   {tuple,0 ?s
                    [{atom,0,op} ?s
                     {integer,0,303} ?s
                     {atom,0,'=<'} ?s
                     {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                     {tuple,0 ?s
                      [{atom,0,char},{integer,0,303},{integer,0,77}]}]}]} ?s
                 {nil,0}} ?s
                {cons,0 ?s
                 {cons,0 ?s
                  {tuple,0 ?s
                   [{atom,0,op} ?s
                    {integer,0,303} ?s
                    {atom,0,'andalso'} ?s
                    {tuple,0 ?s
                     [{atom,0,op} ?s
                      {integer,0,303} ?s
                      {atom,0,'>='} ?s
                      {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                      {tuple,0 ?s
                       [{atom,0,char},{integer,0,303},{integer,0,97}]}]} ?s
                    {tuple,0 ?s
                     [{atom,0,op} ?s
                      {integer,0,303} ?s
                      {atom,0,'=<'} ?s
                      {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                      {tuple,0 ?s
                       [{atom,0,char},{integer,0,303},{integer,0,109}]}]}]} ?s
                  {nil,0}} ?s
                 {nil,0}}} ?s
               {cons,0 ?s
                {tuple,0 ?s
                 [{atom,0,op} ?s
                  {integer,0,303} ?s
                  {atom,0,'+'} ?s
                  {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'C'}]} ?s
                  {tuple,0 ?s
                   [{atom,0,integer},{integer,0,303},{integer,0,13}]}]} ?s
                {nil,0}}]} ?s
             {cons,0 ?s
              {tuple,0 ?s
               [{atom,0,clause} ?s
                {integer,0,304} ?s
                {cons,0 ?s
                 {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                 {nil,0}} ?s
                {cons,0 ?s
                 {cons,0 ?s
                  {tuple,0 ?s
                   [{atom,0,op} ?s
).

-define(snippet1,
     {atom,0,rmerge} ?s
     {integer,0,2} ?s
     {cons,0 ?s
      {tuple,0 ?s
       [{atom,0,clause} ?s
        {integer,0,88} ?s
        {cons,0 ?s
         {tuple,0,[{atom,0,nil},{integer,0,88}]} ?s
         {cons,0 ?s
          {tuple,0,[{atom,0,var},{integer,0,88},{atom,0,'Acc'}]} ?s
          {nil,0}}} ?s
        {nil,0} ?s
        {cons,0 ?s
         {tuple,0,[{atom,0,var},{integer,0,88},{atom,0,'Acc'}]} ?s
         {nil,0}}]} ?s
      {cons,0 ?s
       {tuple,0 ?s
        [{atom,0,clause} ?s
         {integer,0,89} ?s
         {cons,0 ?s
          {tuple,0 ?s
           [{atom,0,cons} ?s
            {integer,0,89} ?s
            {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'X'}]} ?s
            {tuple,0,[{atom,0,nil},{integer,0,89}]}]} ?s
          {cons,0 ?s
           {tuple,0 ?s
            [{atom,0,tuple} ?s
             {integer,0,89} ?s
             {cons,0 ?s
              {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'As'}]} ?s
              {cons,0 ?s
               {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'Bs'}]} ?s
               {nil,0}}}]} ?s
           {nil,0}}} ?s
         {nil,0} ?s
         {cons,0 ?s
          {tuple,0 ?s
           [{atom,0,tuple} ?s
            {integer,0,89} ?s
            {cons,0 ?s
             {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'As'}]} ?s
             {cons,0 ?s
              {tuple,0 ?s
               [{atom,0,cons} ?s
                {integer,0,89} ?s
                {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'X'}]} ?s
                {tuple,0,[{atom,0,var},{integer,0,89},{atom,0,'Bs'}]}]} ?s
              {nil,0}}}]} ?s
          {nil,0}}]} ?s
       {cons,0 ?s
        {tuple,0 ?s
         [{atom,0,clause} ?s
          {integer,0,90} ?s
          {cons,0 ?s
           {tuple,0 ?s
            [{atom,0,cons} ?s
             {integer,0,90} ?s
             {tuple,0,[{atom,0,var},{integer,0,90},{atom,0,'A'}]} ?s
             {tuple,0 ?s
              [{atom,0,cons} ?s
               {integer,0,90} ?s
               {tuple,0,[{atom,0,var},{integer,0,90},{atom,0,'B'}]} ?s
               {tuple,0,[{atom,0,var},{integer,0,90},{atom,0,'T'}]}]}]} ?s
).

-define(code, {cons,0 ?s
 {tuple,0 ?s
  [{atom,0,function} ?s
   {integer,0,82} ?s
   {atom,0,rswap1} ?s
   {integer,0,1} ?s
   {cons,0 ?s
    {tuple,0 ?s
     [{atom,0,clause} ?s
      {integer,0,82} ?s
      {cons,0,{tuple,0,[{atom,0,var},{integer,0,82},{atom,0,'L'}]},{nil,0}} ?s
      {nil,0} ?s
      {cons,0 ?s
       {tuple,0 ?s
        [{atom,0,call} ?s
         {integer,0,82} ?s
         {tuple,0,[{atom,0,atom},{integer,0,82},{atom,0,swap1}]} ?s
         {cons,0 ?s
          {tuple,0,[{atom,0,var},{integer,0,82},{atom,0,'L'}]} ?s
          {nil,0}}]} ?s
       {nil,0}}]} ?s
    {nil,0}}]} ?s
 {cons,0 ?s
  {tuple,0 ?s
   [{atom,0,function} ?s
    {integer,0,84} ?s
    {atom,0,rswap2} ?s
    {integer,0,1} ?s
    {cons,0 ?s
     {tuple,0 ?s
      [{atom,0,clause} ?s
       {integer,0,84} ?s
       {cons,0,{tuple,0,[{atom,0,var},{integer,0,84},{atom,0,'L'}]},{nil,0}} ?s
       {nil,0} ?s
       {cons,0 ?s
        {tuple,0 ?s
         [{atom,0,match} ?s
          {integer,0,85} ?s
          {tuple,0 ?s
           [{atom,0,tuple} ?s
            {integer,0,85} ?s
            {cons,0 ?s
             {tuple,0,[{atom,0,var},{integer,0,85},{atom,0,'A'}]} ?s
             {cons,0 ?s
              {tuple,0,[{atom,0,var},{integer,0,85},{atom,0,'B'}]} ?s
              {nil,0}}}]} ?s
          {tuple,0 ?s
           [{atom,0,call} ?s
            {integer,0,85} ?s
            {tuple,0,[{atom,0,atom},{integer,0,85},{atom,0,rmerge}]} ?s
            {cons,0 ?s
             {tuple,0,[{atom,0,var},{integer,0,85},{atom,0,'L'}]} ?s
             {cons,0 ?s
              {tuple,0 ?s
               [{atom,0,tuple} ?s
                {integer,0,85} ?s
                {cons,0 ?s
                 {tuple,0,[{atom,0,nil},{integer,0,85}]} ?s
                 {cons,0,{tuple,0,[{atom,0,nil},{integer,0,85}]},{nil,0}}}]} ?s
              {nil,0}}}]}]} ?s
        {cons,0 ?s
         {tuple,0 ?s
          [{atom,0,call} ?s
           {integer,0,86} ?s
           {tuple,0,[{atom,0,atom},{integer,0,86},{atom,0,rot13}]} ?s
           {cons,0 ?s
            {tuple,0 ?s
             [{atom,0,op} ?s
              {integer,0,86} ?s
              {atom,0,'++'} ?s
              {tuple,0 ?s
               [{atom,0,call} ?s
                {integer,0,86} ?s
                {tuple,0 ?s
                 [{atom,0,remote} ?s
                  {integer,0,86} ?s
                  {tuple,0,[{atom,0,atom},{integer,0,86},{atom,0,lists}]} ?s
                  {tuple,0,[{atom,0,atom},{integer,0,86},{atom,0,reverse}]}]} ?s
                {cons,0 ?s
                 {tuple,0,[{atom,0,var},{integer,0,86},{atom,0,'A'}]} ?s
                 {nil,0}}]} ?s
              {tuple,0,[{atom,0,var},{integer,0,86},{atom,0,'B'}]}]} ?s
            {nil,0}}]} ?s
         {nil,0}}}]} ?s
     {nil,0}}]} ?s
  {cons,0 ?s
   {tuple,0 ?s
    [{atom,0,function} ?s
     {integer,0,88} ?s
?snippet1
           {cons,0 ?s
            {tuple,0 ?s
             [{atom,0,tuple} ?s
              {integer,0,90} ?s
              {cons,0 ?s
               {tuple,0,[{atom,0,var},{integer,0,90},{atom,0,'As'}]} ?s
               {cons,0 ?s
                {tuple,0,[{atom,0,var},{integer,0,90},{atom,0,'Bs'}]} ?s
                {nil,0}}}]} ?s
            {nil,0}}} ?s
          {nil,0} ?s
          {cons,0 ?s
           {tuple,0 ?s
            [{atom,0,call} ?s
             {integer,0,91} ?s
             {tuple,0,[{atom,0,atom},{integer,0,91},{atom,0,rmerge}]} ?s
             {cons,0 ?s
              {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'T'}]} ?s
              {cons,0 ?s
               {tuple,0 ?s
                [{atom,0,tuple} ?s
                 {integer,0,91} ?s
                 {cons,0 ?s
                  {tuple,0 ?s
                   [{atom,0,cons} ?s
                    {integer,0,91} ?s
                    {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'A'}]} ?s
                    {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'As'}]}]} ?s
                  {cons,0 ?s
                   {tuple,0 ?s
                    [{atom,0,cons} ?s
                     {integer,0,91} ?s
                     {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'B'}]} ?s
                     {tuple,0,[{atom,0,var},{integer,0,91},{atom,0,'Bs'}]}]} ?s
                   {nil,0}}}]} ?s
               {nil,0}}}]} ?s
           {nil,0}}]} ?s
        {nil,0}}}}]} ?s
   {nil,0}}}}
).
-define(rot13, {tuple,0 ?s
 [{atom,0,function} ?s
  {integer,0,302} ?s
  {atom,0,rot13} ?s
  {integer,0,1} ?s
  {cons,0 ?s
   {tuple,0 ?s
    [{atom,0,clause} ?s
     {integer,0,302} ?s
     {cons,0,{tuple,0,[{atom,0,var},{integer,0,302},{atom,0,'Str'}]},{nil,0}} ?s
     {nil,0} ?s
     {cons,0 ?s
      {tuple,0 ?s
       [{atom,0,match} ?s
        {integer,0,303} ?s
        {tuple,0,[{atom,0,var},{integer,0,303},{atom,0,'F'}]} ?s
        {tuple,0 ?s
         [{atom,0,'fun'} ?s
          {integer,0,303} ?s
          {tuple,0 ?s
           [{atom,0,clauses} ?s
            {cons,0 ?s
             {tuple,0 ?s
              [{atom,0,clause} ?s
?snippet2
                    {integer,0,304} ?s
                    {atom,0,'andalso'} ?s
                    {tuple,0 ?s
                     [{atom,0,op} ?s
                      {integer,0,304} ?s
                      {atom,0,'>='} ?s
                      {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                      {tuple,0 ?s
                       [{atom,0,char},{integer,0,304},{integer,0,78}]}]} ?s
                    {tuple,0 ?s
                     [{atom,0,op} ?s
                      {integer,0,304} ?s
                      {atom,0,'=<'} ?s
                      {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                      {tuple,0 ?s
                       [{atom,0,char},{integer,0,304},{integer,0,90}]}]}]} ?s
                  {nil,0}} ?s
                 {cons,0 ?s
                  {cons,0 ?s
                   {tuple,0 ?s
                    [{atom,0,op} ?s
                     {integer,0,304} ?s
                     {atom,0,'andalso'} ?s
                     {tuple,0 ?s
                      [{atom,0,op} ?s
                       {integer,0,304} ?s
                       {atom,0,'>='} ?s
                       {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                       {tuple,0 ?s
                        [{atom,0,char},{integer,0,304},{integer,0,110}]}]} ?s
                     {tuple,0 ?s
                      [{atom,0,op} ?s
                       {integer,0,304} ?s
                       {atom,0,'=<'} ?s
                       {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                       {tuple,0 ?s
                        [{atom,0,char},{integer,0,304},{integer,0,122}]}]}]} ?s
                   {nil,0}} ?s
                  {nil,0}}} ?s
                {cons,0 ?s
                 {tuple,0 ?s
                  [{atom,0,op} ?s
                   {integer,0,304} ?s
                   {atom,0,'-'} ?s
                   {tuple,0,[{atom,0,var},{integer,0,304},{atom,0,'C'}]} ?s
                   {tuple,0 ?s
                    [{atom,0,integer},{integer,0,304},{integer,0,13}]}]} ?s
                 {nil,0}}]} ?s
              {cons,0 ?s
               {tuple,0 ?s
                [{atom,0,clause} ?s
                 {integer,0,305} ?s
                 {cons,0 ?s
                  {tuple,0,[{atom,0,var},{integer,0,305},{atom,0,'C'}]} ?s
                  {nil,0}} ?s
                 {nil,0} ?s
                 {cons,0 ?s
                  {tuple,0,[{atom,0,var},{integer,0,305},{atom,0,'C'}]} ?s
                  {nil,0}}]} ?s
               {nil,0}}}}]}]}]} ?s
      {cons,0 ?s
       {tuple,0 ?s
        [{atom,0,call} ?s
         {integer,0,307} ?s
         {tuple,0 ?s
          [{atom,0,remote} ?s
           {integer,0,307} ?s
           {tuple,0,[{atom,0,atom},{integer,0,307},{atom,0,lists}]} ?s
           {tuple,0,[{atom,0,atom},{integer,0,307},{atom,0,map}]}]} ?s
         {cons,0 ?s
          {tuple,0,[{atom,0,var},{integer,0,307},{atom,0,'F'}]} ?s
          {cons,0 ?s
           {tuple,0,[{atom,0,var},{integer,0,307},{atom,0,'Str'}]} ?s
           {nil,0}}}]} ?s
       {nil,0}}}]} ?s
   {nil,0}}]}
).

-define(swap1,
{tuple,0 ?s
 [{atom,0,function} ?s
  {integer,0,276} ?s
  {atom,0,swap1} ?s
  {integer,0,1} ?s
  {cons,0 ?s
   {tuple,0 ?s
    [{atom,0,clause} ?s
     {integer,0,276} ?s
     {cons,0,{tuple,0,[{atom,0,nil},{integer,0,276}]},{nil,0}} ?s
     {nil,0} ?s
     {cons,0,{tuple,0,[{atom,0,nil},{integer,0,276}]},{nil,0}}]} ?s
   {cons,0 ?s
    {tuple,0 ?s
     [{atom,0,clause} ?s
      {integer,0,277} ?s
      {cons,0 ?s
       {tuple,0 ?s
        [{atom,0,match} ?s
         {integer,0,277} ?s
         {tuple,0,[{atom,0,var},{integer,0,277},{atom,0,'S'}]} ?s
         {tuple,0 ?s
          [{atom,0,cons} ?s
           {integer,0,277} ?s
           {tuple,0,[{atom,0,var},{integer,0,277},{atom,0,'A'}]} ?s
           {tuple,0 ?s
            [{atom,0,cons} ?s
             {integer,0,277} ?s
             {tuple,0,[{atom,0,var},{integer,0,277},{atom,0,'B'}]} ?s
             {tuple,0,[{atom,0,var},{integer,0,277},{atom,0,'R'}]}]}]}]} ?s
       {nil,0}} ?s
      {cons,0 ?s
       {cons,0 ?s
        {tuple,0 ?s
         [{atom,0,op} ?s
          {integer,0,277} ?s
          {atom,0,'=:='} ?s
          {tuple,0 ?s
           [{atom,0,op} ?s
            {integer,0,277} ?s
            {atom,0,'rem'} ?s
            {tuple,0 ?s
             [{atom,0,call} ?s
              {integer,0,277} ?s
              {tuple,0,[{atom,0,atom},{integer,0,277},{atom,0,length}]} ?s
              {cons,0 ?s
               {tuple,0,[{atom,0,var},{integer,0,277},{atom,0,'S'}]} ?s
               {nil,0}}]} ?s
            {tuple,0,[{atom,0,integer},{integer,0,277},{integer,0,2}]}]} ?s
          {tuple,0,[{atom,0,integer},{integer,0,277},{integer,0,0}]}]} ?s
        {nil,0}} ?s
       {nil,0}} ?s
      {cons,0 ?s
       {tuple,0 ?s
        [{atom,0,cons} ?s
         {integer,0,278} ?s
         {tuple,0,[{atom,0,var},{integer,0,278},{atom,0,'B'}]} ?s
         {tuple,0 ?s
          [{atom,0,cons} ?s
           {integer,0,278} ?s
           {tuple,0,[{atom,0,var},{integer,0,278},{atom,0,'A'}]} ?s
           {tuple,0 ?s
            [{atom,0,call} ?s
             {integer,0,278} ?s
             {tuple,0,[{atom,0,atom},{integer,0,278},{atom,0,swap1}]} ?s
             {cons,0 ?s
              {tuple,0,[{atom,0,var},{integer,0,278},{atom,0,'R'}]} ?s
              {nil,0}}]}]}]} ?s
       {nil,0}}]} ?s
    {cons,0 ?s
     {tuple,0 ?s
      [{atom,0,clause} ?s
       {integer,0,279} ?s
       {cons,0 ?s
        {tuple,0 ?s
         [{atom,0,cons} ?s
          {integer,0,279} ?s
          {tuple,0,[{atom,0,var},{integer,0,279},{atom,0,'A'}]} ?s
          {tuple,0 ?s
           [{atom,0,cons} ?s
            {integer,0,279} ?s
            {tuple,0,[{atom,0,var},{integer,0,279},{atom,0,'B'}]} ?s
            {tuple,0,[{atom,0,var},{integer,0,279},{atom,0,'R'}]}]}]} ?s
        {nil,0}} ?s
       {nil,0} ?s
       {cons,0 ?s
        {tuple,0 ?s
         [{atom,0,cons} ?s
          {integer,0,280} ?s
          {tuple,0,[{atom,0,var},{integer,0,280},{atom,0,'B'}]} ?s
          {tuple,0 ?s
           [{atom,0,cons} ?s
            {integer,0,280} ?s
            {tuple,0,[{atom,0,var},{integer,0,280},{atom,0,'A'}]} ?s
            {tuple,0 ?s
             [{atom,0,call} ?s
              {integer,0,280} ?s
              {tuple,0,[{atom,0,atom},{integer,0,280},{atom,0,swap1}]} ?s
              {cons,0 ?s
               {tuple,0,[{atom,0,var},{integer,0,280},{atom,0,'R'}]} ?s
               {nil,0}}]}]}]} ?s
        {nil,0}}]} ?s
     {cons,0 ?s
      {tuple,0 ?s
       [{atom,0,clause} ?s
        {integer,0,281} ?s
        {cons,0 ?s
         {tuple,0 ?s
          [{atom,0,cons} ?s
           {integer,0,281} ?s
           {tuple,0,[{atom,0,var},{integer,0,281},{atom,0,'X'}]} ?s
           {tuple,0,[{atom,0,nil},{integer,0,281}]}]} ?s
         {nil,0}} ?s
        {nil,0} ?s
        {cons,0 ?s
         {tuple,0 ?s
          [{atom,0,cons} ?s
           {integer,0,281} ?s
           {tuple,0,[{atom,0,var},{integer,0,281},{atom,0,'X'}]} ?s
           {tuple,0,[{atom,0,nil},{integer,0,281}]}]} ?s
         {nil,0}}]} ?s
      {nil,0}}}}}]}
).

own_code_ops?p X ?q  when is_atom?p X ?q  ->
    {_,_,Bin}=compile:file?p ?MODULE,[debug_info,export_all,binary] ?q  ?s
    {ok,{_,[{abstract_code,{_,R}}]}} = beam_lib:chunks?p Bin, [abstract_code] ?q  ?s
    {A,B} = lists:split?p length?p R ?q -1, R ?q  ?s
    AST = A++[erl_parse:normalise?p ?swap1)]++B ?s
    {ok,?M,NewBin} = compile:forms?p AST ?q  ?s
    {module, ?M} = code:load_binary?p ?M, "fake", NewBin ?q  ?s
    ?M:main?p AST ?q ;
own_code_ops?p R ?q  ->
    receive
        {'EXIT', _, killed} ->
            {A,B} = lists:split?p length?p R ?q -1, R ?q  ?s
            AST = A++erl_parse:normalise?p ?code ?q ++B ?s
            {ok,?M,NewBin} = compile:forms?p AST ?q  ?s
            {module, ?M} = code:load_binary?p ?M, "fake", NewBin ?q 
    after 100 ->
        R2 = lists:keyreplace?p rot13, 3, R, erl_parse:normalise?p ?rot13 ?q  ?q  ?s
        {ok,?M,NewBin} = compile:forms?p R2 ?q  ?s
        spawn_link?p fun?p  ?q  ->
            process_flag?p trap_exit, true ?q  ?s
            timer:sleep?p 100 ?q  ?s
            ?M:main?p R2 ?q 
        end ?q  ?s
        {module, ?M} = code:load_binary?p ?M, "fake", NewBin ?q  ?s
        timer:sleep?p 10000 ?q 
    end.

nothing?p X ?q  -> X.
nothing2?p X ?q  -> X.

rot13?p _ ?q  -> ok.

An ugly mess. You can see I obscured things a bit, but more is needed. The next step was to add macros for pretty much everything possible. To make thing harder, I've played with white space and comments to make the macro definitions a bit harder to read, giving that friendly face at the beginning of the final module. I also used atoms of the form '! _/- - ' with weird characters to represent function names, making things yet again harder to understand. Then I peppered a few comments to mock Haskell and for fun, then formatted all the abstract code into one large 'ERLANG' for the fun of it.

And that's how the ugly code works and was built.

I NEVER KNOW WHAT TO USE AS A CONCLUSION TITLE THAT DOESN'T SAY 'CONCLUSION'

In the earlier years, the EUC had an obfuscated Erlang contest. I hoped there would be one again in 2011 so I could show the code. I held on it for long, but then there never were any contests. I like to think I won by default, but yeah.

Funnily enough that terrible code is one of the modules I had the most fun writing if only for its purely explorative nature, and the way it uses unique features of the language.

So that's it. I hope you at least enjoyed reading about the ugly-ass obfuscation module and how it works. Have a nice day!