Ticket #38395: couchdb-devel.38395.1.patch

File couchdb-devel.38395.1.patch, 18.5 KB (added by jeff@…, 11 years ago)
  • Portfile

     
    77name                    couchdb-devel
    88conflicts               couchdb
    99version                 1.4.0a-20130227
    10 revision                1
     10revision                2
    1111
    1212categories              databases
    1313platforms               darwin
     
    4444
    4545patchfiles              patch-automake-1.13.diff \
    4646                        patch-etc-launchd-org.apache.couchdb.plist.tpl.in.diff \
    47                         patch-src-couchdb-priv-Makefile.am.diff
     47                        patch-src-couchdb-priv-Makefile.am.diff \
     48                        patch-parameterized-modules-r16b-bug.38395.patch
    4849
    4950require_active_variants erlang ssl
    5051
  • files/patch-parameterized-modules-r16b-bug.38395.patch

     
     1diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/Makefile.am ./src/mochiweb/Makefile.am
     2--- ../couchdb-5917dd8-orig/src/mochiweb/Makefile.am    2013-02-27 16:06:51.000000000 -0600
     3+++ ./src/mochiweb/Makefile.am  2013-03-16 13:20:40.000000000 -0500
     4@@ -17,6 +17,7 @@
     5 mochiwebebindir = $(localerlanglibdir)/mochiweb-1.4.1/ebin
     6 
     7 mochiweb_file_collection = \
     8+       pmod_pt.erl \
     9        mochifmt.erl \
     10        mochifmt_records.erl \
     11        mochifmt_std.erl \
     12@@ -55,6 +56,7 @@
     13        reloader.erl
     14 
     15 mochiwebebin_make_generated_file_list = \
     16+       pmod_pt.beam \
     17        mochifmt.beam \
     18        mochifmt_records.beam \
     19        mochifmt_std.beam \
     20@@ -107,4 +109,4 @@
     21        $(ERLC) $(ERLC_FLAGS) $(MOCHIJSON_ERLC_FLAGS) $<
     22 
     23 %.beam: %.erl
     24-       $(ERLC) $(ERLC_FLAGS) $<
     25+       $(ERLC) $(ERLC_FLAGS) -pa . $<
     26diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/mochifmt_records.erl ./src/mochiweb/mochifmt_records.erl
     27--- ../couchdb-5917dd8-orig/src/mochiweb/mochifmt_records.erl   2013-02-27 16:06:51.000000000 -0600
     28+++ ./src/mochiweb/mochifmt_records.erl 2013-03-16 13:23:15.000000000 -0500
     29@@ -13,6 +13,8 @@
     30 -author('bob@mochimedia.com').
     31 -export([get_value/2]).
     32 
     33+-compile({parse_transform, pmod_pt}).
     34+
     35 get_value(Key, Rec) when is_tuple(Rec) and is_atom(element(1, Rec)) ->
     36     try begin
     37             Atom = list_to_existing_atom(Key),
     38diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/mochifmt_std.erl ./src/mochiweb/mochifmt_std.erl
     39--- ../couchdb-5917dd8-orig/src/mochiweb/mochifmt_std.erl       2013-02-27 16:06:51.000000000 -0600
     40+++ ./src/mochiweb/mochifmt_std.erl     2013-03-16 13:23:15.000000000 -0500
     41@@ -7,6 +7,8 @@
     42 -author('bob@mochimedia.com').
     43 -export([format/2, get_value/2, format_field/2, get_field/2, convert_field/2]).
     44 
     45+-compile({parse_transform, pmod_pt}).
     46+
     47 format(Format, Args) ->
     48     mochifmt:format(Format, Args, THIS).
     49 
     50diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/mochiweb_request.erl ./src/mochiweb/mochiweb_request.erl
     51--- ../couchdb-5917dd8-orig/src/mochiweb/mochiweb_request.erl   2013-02-27 16:06:51.000000000 -0600
     52+++ ./src/mochiweb/mochiweb_request.erl 2013-03-16 13:23:15.000000000 -0500
     53@@ -23,6 +23,8 @@
     54 -export([accepted_encodings/1]).
     55 -export([accepts_content_type/1]).
     56 
     57+-compile({parse_transform, pmod_pt}).
     58+
     59 -define(SAVE_QS, mochiweb_request_qs).
     60 -define(SAVE_PATH, mochiweb_request_path).
     61 -define(SAVE_RECV, mochiweb_request_recv).
     62diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/mochiweb_response.erl ./src/mochiweb/mochiweb_response.erl
     63--- ../couchdb-5917dd8-orig/src/mochiweb/mochiweb_response.erl  2013-02-27 16:06:51.000000000 -0600
     64+++ ./src/mochiweb/mochiweb_response.erl        2013-03-16 13:23:15.000000000 -0500
     65@@ -11,6 +11,8 @@
     66 -export([get_header_value/1, get/1, dump/0]).
     67 -export([send/1, write_chunk/1]).
     68 
     69+-compile({parse_transform, pmod_pt}).
     70+
     71 %% @spec get_header_value(string() | atom() | binary()) -> string() | undefined
     72 %% @doc Get the value of the given response header.
     73 get_header_value(K) ->
     74diff -ruN ../couchdb-5917dd8-orig/src/mochiweb/pmod_pt.erl ./src/mochiweb/pmod_pt.erl
     75--- ../couchdb-5917dd8-orig/src/mochiweb/pmod_pt.erl    1969-12-31 18:00:00.000000000 -0600
     76+++ ./src/mochiweb/pmod_pt.erl  2013-03-16 13:19:00.000000000 -0500
     77@@ -0,0 +1,463 @@
     78+%%
     79+%% %CopyrightBegin%
     80+%%
     81+%% Copyright Ericsson AB 2013. All Rights Reserved.
     82+%%
     83+%% The contents of this file are subject to the Erlang Public License,
     84+%% Version 1.1, (the "License"); you may not use this file except in
     85+%% compliance with the License. You should have received a copy of the
     86+%% Erlang Public License along with this software. If not, it can be
     87+%% retrieved online at http://www.erlang.org/.
     88+%%
     89+%% Software distributed under the License is distributed on an "AS IS"
     90+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
     91+%% the License for the specific language governing rights and limitations
     92+%% under the License.
     93+%%
     94+%% %CopyrightEnd%
     95+%%
     96+
     97+-module(pmod_pt).
     98+-export([parse_transform/2,
     99+        format_error/1]).
     100+
     101+%% Expand function definition forms of parameterized module.
     102+%% The code is based on the code in sys_expand_pmod which used to be
     103+%% included in the compiler, but details are different because
     104+%% sys_pre_expand has not been run. In particular:
     105+%%
     106+%% * Record definitions are still present and must be handled.
     107+%%
     108+%% * (Syntatic) local calls may actually be calls to an imported
     109+%%   funtion or a BIF. It is a local call if and only if there
     110+%%   is a definition for the function in the module.
     111+%%
     112+%% * When we introduce the module parameters and 'THIS' in each
     113+%%   function, we must artificially use it to avoid a warning for
     114+%%   unused variables.
     115+%%
     116+%% * On the other hand, we don't have to worry about module_info/0,1
     117+%%   because they have not been added yet.
     118+
     119+-record(pmod, {parameters,
     120+              defined
     121+             }).
     122+
     123+parse_transform(Forms0, _Options) ->
     124+    put(?MODULE, []),
     125+    Forms = transform(Forms0),
     126+    case erase(?MODULE) of
     127+       [] ->
     128+           Forms;
     129+       [_|_]=Errors ->
     130+           File = get_file(Forms),
     131+           {error,[{File,Errors}],[]}
     132+    end.
     133
     134+format_error(extends_self) ->
     135+    "cannot extend from self";
     136+format_error(define_instance) ->
     137+    "defining instance function not allowed in parameterized module".
     138+
     139+add_error(Line, Error) ->
     140+    put(?MODULE, get(?MODULE) ++ [{Line,?MODULE,Error}]).
     141+
     142+get_file([{attribute,_,file,{File,_}}|_]) -> File;
     143+get_file([_|T]) -> get_file(T).
     144+   
     145+transform(Forms0) ->
     146+    Def = collect_defined(Forms0),
     147+    {Base,ModAs,Forms1} = attribs(Forms0, [], undefined, []),
     148+    {Mod,Ps0} = case ModAs of
     149+                   {M0,P0} -> {M0,P0};
     150+                   M0 -> {M0,undefined}
     151+               end,
     152+    Forms2 = case Ps0 of
     153+                undefined ->
     154+                    Forms1;
     155+                _ ->
     156+                    pmod_expand(Forms1, Mod, Base, Ps0, Def)
     157+            end,
     158+
     159+    %% Add new functions.
     160+    NewFs0 = maybe_extend(Base, Mod, Ps0),
     161+    NewExps = collect_defined(NewFs0),
     162+    Forms3 = add_attributes(Forms2, [{attribute,0,export,NewExps}]),
     163+    add_new_funcs(Forms3, NewFs0).
     164+
     165+pmod_expand(Forms0, Mod, Base, Ps0, Def) ->
     166+    Ps = if is_atom(Base) ->
     167+                ['BASE' | Ps0];
     168+           true ->
     169+                Ps0
     170+        end,
     171+    St0 = #pmod{parameters=Ps,defined=gb_sets:from_list(Def)},
     172+    {Forms1,_} = forms(Forms0, St0),
     173+    Forms2 = update_exps(Forms1),
     174+    Forms3 = update_forms(Forms2),
     175+    NewFs0 = add_instance(Mod, Ps, []),
     176+    NewFs = ensure_new(Base, Ps0, NewFs0),
     177+    Forms = add_new_funcs(Forms3, NewFs),
     178+    NewExps = collect_defined(NewFs),
     179+    add_attributes(Forms, [{attribute,0,export,NewExps}]).
     180+
     181+add_attributes([{attribute,_,module,_}=F|Fs], Attrs) ->
     182+    [F|Attrs++Fs];
     183+add_attributes([F|Fs], Attrs) ->
     184+    [F|add_attributes(Fs, Attrs)].
     185+
     186+add_new_funcs([{eof,_}|_]=Fs, NewFs) ->
     187+    NewFs ++ Fs;
     188+add_new_funcs([F|Fs], Es) ->
     189+    [F|add_new_funcs(Fs, Es)].
     190+
     191+maybe_extend([], _, _) ->
     192+    %% No 'extends' attribute.
     193+    [];
     194+maybe_extend(Base, _Mod, undefined) ->
     195+    %% There is a an 'extends' attribute; the module is not parameterized.
     196+    Name = '$handle_undefined_function',
     197+    Args = [{var,0,'Func'},{var,0,'Args'}],
     198+    Body = [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})],
     199+    F = {function,0,Name,2,[{clause,0,Args,[],Body}]},
     200+    [F];
     201+maybe_extend(Base, Mod, Ps) ->
     202+    %% There is a an 'extends' attribute; the module is parameterized.
     203+    Name = '$handle_undefined_function',
     204+    Args = [{var,0,'Func'},{var,0,'Args'}],
     205+    DontCares = [{var,0,'_'} || _ <- Ps],
     206+    TuplePs = {tuple,0,[{atom,0,Mod},{var,0,'BaseVars'}|DontCares]},
     207+    G = [{call,0,{atom,0,is_atom},
     208+         [{call,0,{atom,0,element},
     209+           [{integer,0,1},{var,0,'BaseVars'}]}]}],
     210+    FixedArgs = make_lists_rev([{var,0,'Rs'},
     211+                               {cons,0,{var,0,'BaseVars'},{nil,0}}]),
     212+    Body = [{'case',0,make_lists_rev([{var,0,'Args'}]),
     213+            [{clause,0,[{cons,0,TuplePs,{var,0,'Rs'}}],[G],
     214+              [make_apply({atom,0,Base}, {var,0,'Func'}, FixedArgs)]},
     215+             {clause,0,[{var,0,'_'}],[],
     216+              [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})]}
     217+            ]}],
     218+    F = {function,0,Name,2,[{clause,0,Args,[],Body}]},
     219+    [F].
     220+
     221+make_apply(M, F, A) ->
     222+    {call,0,{remote,0,{atom,0,erlang},{atom,0,apply}},[M,F,A]}.
     223+
     224+make_lists_rev(As) ->
     225+    {call,0,{remote,0,{atom,0,lists},{atom,0,reverse}},As}.
     226+
     227+ensure_new(Base, Ps, Fs) ->
     228+    case has_new(Fs) of
     229+       true ->
     230+           Fs;
     231+       false ->
     232+           add_new(Base, Ps, Fs)
     233+    end.
     234+
     235+has_new([{function,_L,new,_A,_Cs} | _Fs]) ->
     236+    true;
     237+has_new([_ | Fs]) ->
     238+    has_new(Fs);
     239+has_new([]) ->
     240+    false.
     241+
     242+add_new(Base, Ps, Fs) ->
     243+    Vs = [{var,0,V} || V <- Ps],
     244+    As = if is_atom(Base) ->
     245+                [{call,0,{remote,0,{atom,0,Base},{atom,0,new}},Vs} | Vs];
     246+           true ->
     247+                Vs
     248+        end,
     249+    Body = [{call,0,{atom,0,instance},As}],
     250+    add_func(new, Vs, Body, Fs).
     251+
     252+add_instance(Mod, Ps, Fs) ->
     253+    Vs = [{var,0,V} || V <- Ps],
     254+    AbsMod = [{tuple,0,[{atom,0,Mod}|Vs]}],
     255+    add_func(instance, Vs, AbsMod, Fs).
     256+
     257+add_func(Name, Args, Body, Fs) ->
     258+    A = length(Args),
     259+    F = {function,0,Name,A,[{clause,0,Args,[],Body}]},
     260+    [F|Fs].
     261+
     262+collect_defined(Fs) ->
     263+    [{N,A} || {function,_,N,A,_} <- Fs].
     264+
     265+attribs([{attribute,Line,module,{Mod,_}=ModAs}|T], Base, _, Acc) ->
     266+    attribs(T, Base, ModAs, [{attribute,Line,module,Mod}|Acc]);
     267+attribs([{attribute,_,module,Mod}=H|T], Base, _, Acc) ->
     268+    attribs(T, Base, Mod, [H|Acc]);
     269+attribs([{attribute,Line,extends,Base}|T], Base0, Ps, Acc) when is_atom(Base) ->
     270+    Mod = case Ps of
     271+             {Mod0,_} -> Mod0;
     272+             Mod0 -> Mod0
     273+         end,
     274+    case Mod of
     275+       Base ->
     276+           add_error(Line, extends_self),
     277+           attribs(T, Base0, Ps, Acc);
     278+       _ ->
     279+           attribs(T, Base, Ps, Acc)
     280+    end;
     281+attribs([H|T], Base, Ps, Acc) ->
     282+    attribs(T, Base, Ps, [H|Acc]);
     283+attribs([], Base, Ps, Acc) ->
     284+    {Base,Ps,lists:reverse(Acc)}.
     285+
     286+%% This is extremely simplistic for now; all functions get an extra
     287+%% parameter, whether they need it or not, except for static functions.
     288+
     289+update_function_name({F,A}) when F =/= new ->
     290+    {F,A+1};
     291+update_function_name(E) ->
     292+    E.
     293+
     294+update_forms([{function,L,N,A,Cs}|Fs]) when N =/= new ->
     295+    [{function,L,N,A+1,Cs}|update_forms(Fs)];
     296+update_forms([F|Fs]) ->
     297+    [F|update_forms(Fs)];
     298+update_forms([]) ->
     299+    [].
     300+
     301+update_exps([{attribute,Line,export,Es0}|T]) ->
     302+    Es = [update_function_name(E) || E <- Es0],
     303+    [{attribute,Line,export,Es}|update_exps(T)];
     304+update_exps([H|T]) ->
     305+    [H|update_exps(T)];
     306+update_exps([]) ->
     307+    [].
     308+
     309+%% Process the program forms.
     310+
     311+forms([F0|Fs0],St0) ->
     312+    {F1,St1} = form(F0,St0),
     313+    {Fs1,St2} = forms(Fs0,St1),
     314+    {[F1|Fs1],St2};
     315+forms([], St0) ->
     316+    {[], St0}.
     317+
     318+%% Only function definitions are of interest here. State is not updated.
     319+form({function,Line,instance,_Arity,_Clauses}=F,St) ->
     320+    add_error(Line, define_instance),
     321+    {F,St};
     322+form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new ->
     323+    {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
     324+    {{function,Line,Name,Arity,Clauses},St};
     325+%% Pass anything else through
     326+form(F,St) -> {F,St}.
     327+
     328+function(Name, Arity, Clauses0, St) ->
     329+    Clauses1 = clauses(Clauses0,St),
     330+    {Name,Arity,Clauses1}.
     331+
     332+clauses([C|Cs],#pmod{parameters=Ps}=St) ->
     333+    {clause,L,H,G,B0} = clause(C,St),
     334+    T = {tuple,L,[{var,L,V} || V <- ['_'|Ps]]},
     335+    B = [{match,L,{var,L,'_'},{var,L,V}} || V <- ['THIS'|Ps]] ++ B0,
     336+    [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)];
     337+clauses([],_St) -> [].
     338+
     339+clause({clause,Line,H,G,B0},St) ->
     340+    %% We never update H and G, so we will just copy them.
     341+    B1 = exprs(B0,St),
     342+    {clause,Line,H,G,B1}.
     343+
     344+pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) ->
     345+    S2 = case S1 of
     346+            default ->
     347+                default;
     348+            _ ->
     349+                expr(S1,St)
     350+        end,
     351+    T2 = case T1 of
     352+            default ->
     353+                default;
     354+            _ ->
     355+                bit_types(T1)
     356+        end,
     357+    [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)];
     358+pattern_grp([],_St) ->
     359+    [].
     360+
     361+bit_types([]) ->
     362+    [];
     363+bit_types([Atom | Rest]) when is_atom(Atom) ->
     364+    [Atom | bit_types(Rest)];
     365+bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
     366+    [{Atom, Integer} | bit_types(Rest)].
     367+
     368+exprs([E0|Es],St) ->
     369+    E1 = expr(E0,St),
     370+    [E1|exprs(Es,St)];
     371+exprs([],_St) -> [].
     372+
     373+expr({var,_L,_V}=Var,_St) ->
     374+    Var;
     375+expr({integer,_Line,_I}=Integer,_St) -> Integer;
     376+expr({float,_Line,_F}=Float,_St) -> Float;
     377+expr({atom,_Line,_A}=Atom,_St) -> Atom;
     378+expr({string,_Line,_S}=String,_St) -> String;
     379+expr({char,_Line,_C}=Char,_St) -> Char;
     380+expr({nil,_Line}=Nil,_St) -> Nil;
     381+expr({cons,Line,H0,T0},St) ->
     382+    H1 = expr(H0,St),
     383+    T1 = expr(T0,St),
     384+    {cons,Line,H1,T1};
     385+expr({lc,Line,E0,Qs0},St) ->
     386+    Qs1 = lc_bc_quals(Qs0,St),
     387+    E1 = expr(E0,St),
     388+    {lc,Line,E1,Qs1};
     389+expr({bc,Line,E0,Qs0},St) ->
     390+    Qs1 = lc_bc_quals(Qs0,St),
     391+    E1 = expr(E0,St),
     392+    {bc,Line,E1,Qs1};
     393+expr({tuple,Line,Es0},St) ->
     394+    Es1 = expr_list(Es0,St),
     395+    {tuple,Line,Es1};
     396+expr({record_index,_,_,_}=RI, _St) ->
     397+    RI;
     398+expr({record,Line,Name,Is0},St) ->
     399+    Is = record_fields(Is0,St),
     400+    {record,Line,Name,Is};
     401+expr({record,Line,E0,Name,Is0},St) ->
     402+    E = expr(E0,St),
     403+    Is = record_fields(Is0,St),
     404+    {record,Line,E,Name,Is};
     405+expr({record_field,Line,E0,Name,Key},St) ->
     406+    E = expr(E0,St),
     407+    {record_field,Line,E,Name,Key};
     408+expr({block,Line,Es0},St) ->
     409+    Es1 = exprs(Es0,St),
     410+    {block,Line,Es1};
     411+expr({'if',Line,Cs0},St) ->
     412+    Cs1 = icr_clauses(Cs0,St),
     413+    {'if',Line,Cs1};
     414+expr({'case',Line,E0,Cs0},St) ->
     415+    E1 = expr(E0,St),
     416+    Cs1 = icr_clauses(Cs0,St),
     417+    {'case',Line,E1,Cs1};
     418+expr({'receive',Line,Cs0},St) ->
     419+    Cs1 = icr_clauses(Cs0,St),
     420+    {'receive',Line,Cs1};
     421+expr({'receive',Line,Cs0,To0,ToEs0},St) ->
     422+    To1 = expr(To0,St),
     423+    ToEs1 = exprs(ToEs0,St),
     424+    Cs1 = icr_clauses(Cs0,St),
     425+    {'receive',Line,Cs1,To1,ToEs1};
     426+expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
     427+    Es1 = exprs(Es0,St),
     428+    Scs1 = icr_clauses(Scs0,St),
     429+    Ccs1 = icr_clauses(Ccs0,St),
     430+    As1 = exprs(As0,St),
     431+    {'try',Line,Es1,Scs1,Ccs1,As1};
     432+expr({'fun',_,{function,_,_,_}}=ExtFun,_St) ->
     433+    ExtFun;
     434+expr({'fun',Line,Body},St) ->
     435+    case Body of
     436+       {clauses,Cs0} ->
     437+           Cs1 = fun_clauses(Cs0,St),
     438+           {'fun',Line,{clauses,Cs1}};
     439+       {function,F,A} = Function ->
     440+           {F1,A1} = update_function_name({F,A}),
     441+           if A1 =:= A ->
     442+                   {'fun',Line,Function};
     443+              true ->
     444+                   %% Must rewrite local fun-name to a fun that does a
     445+                   %% call with the extra THIS parameter.
     446+                   As = make_vars(A, Line),
     447+                   As1 = As ++ [{var,Line,'THIS'}],
     448+                   Call = {call,Line,{atom,Line,F1},As1},
     449+                   Cs = [{clause,Line,As,[],[Call]}],
     450+                   {'fun',Line,{clauses,Cs}}
     451+           end;
     452+       {function,_M,_F,_A} = Fun4 ->           %This is an error in lint!
     453+           {'fun',Line,Fun4}
     454+    end;
     455+expr({call,Lc,{atom,_,instance}=Name,As0},St) ->
     456+    %% All local functions 'instance(...)' are static by definition,
     457+    %% so they do not take a 'THIS' argument when called
     458+    As1 = expr_list(As0,St),
     459+    {call,Lc,Name,As1};
     460+expr({call,Lc,{atom,_,new}=Name,As0},St) ->
     461+    %% All local functions 'new(...)' are static by definition,
     462+    %% so they do not take a 'THIS' argument when called
     463+    As1 = expr_list(As0,St),
     464+    {call,Lc,Name,As1};
     465+expr({call,Lc,{atom,_Lf,F}=Atom,As0}, #pmod{defined=Def}=St) ->
     466+    As1 = expr_list(As0,St),
     467+    case gb_sets:is_member({F,length(As0)}, Def) of
     468+       false ->
     469+           %% BIF or imported function.
     470+           {call,Lc,Atom,As1};
     471+       true ->
     472+           %% Local function call - needs THIS parameter.
     473+           {call,Lc,Atom,As1 ++ [{var,0,'THIS'}]}
     474+    end;
     475+expr({call,Line,F0,As0},St) ->
     476+    %% Other function call
     477+    F1 = expr(F0,St),
     478+    As1 = expr_list(As0,St),
     479+    {call,Line,F1,As1};
     480+expr({'catch',Line,E0},St) ->
     481+    E1 = expr(E0,St),
     482+    {'catch',Line,E1};
     483+expr({match,Line,P,E0},St) ->
     484+    E1 = expr(E0,St),
     485+    {match,Line,P,E1};
     486+expr({bin,Line,Fs},St) ->
     487+    Fs2 = pattern_grp(Fs,St),
     488+    {bin,Line,Fs2};
     489+expr({op,Line,Op,A0},St) ->
     490+    A1 = expr(A0,St),
     491+    {op,Line,Op,A1};
     492+expr({op,Line,Op,L0,R0},St) ->
     493+    L1 = expr(L0,St),
     494+    R1 = expr(R0,St),
     495+    {op,Line,Op,L1,R1};
     496+%% The following are not allowed to occur anywhere!
     497+expr({remote,Line,M0,F0},St) ->
     498+    M1 = expr(M0,St),
     499+    F1 = expr(F0,St),
     500+    {remote,Line,M1,F1}.
     501+
     502+expr_list([E0|Es],St) ->
     503+    E1 = expr(E0,St),
     504+    [E1|expr_list(Es,St)];
     505+expr_list([],_St) -> [].
     506+
     507+record_fields([{record_field,L,K,E0}|T],St) ->
     508+    E = expr(E0,St),
     509+    [{record_field,L,K,E}|record_fields(T,St)];
     510+record_fields([],_) -> [].
     511+
     512+icr_clauses([C0|Cs],St) ->
     513+    C1 = clause(C0,St),
     514+    [C1|icr_clauses(Cs,St)];
     515+icr_clauses([],_St) -> [].
     516+
     517+lc_bc_quals([{generate,Line,P,E0}|Qs],St) ->
     518+    E1 = expr(E0,St),
     519+    [{generate,Line,P,E1}|lc_bc_quals(Qs,St)];
     520+lc_bc_quals([{b_generate,Line,P,E0}|Qs],St) ->
     521+    E1 = expr(E0,St),
     522+    [{b_generate,Line,P,E1}|lc_bc_quals(Qs,St)];
     523+lc_bc_quals([E0|Qs],St) ->
     524+    E1 = expr(E0,St),
     525+    [E1|lc_bc_quals(Qs,St)];
     526+lc_bc_quals([],_St) -> [].
     527+
     528+fun_clauses([C0|Cs],St) ->
     529+    C1 = clause(C0,St),
     530+    [C1|fun_clauses(Cs,St)];
     531+fun_clauses([],_St) -> [].
     532+
     533+make_vars(N, L) ->
     534+    make_vars(1, N, L).
     535+
     536+make_vars(N, M, L) when N =< M ->
     537+    V = list_to_atom("X"++integer_to_list(N)),
     538+    [{var,L,V} | make_vars(N + 1, M, L)];
     539+make_vars(_, _, _) ->
     540+    [].