| 1 | diff -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 . $< |
| 26 | diff -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), |
| 38 | diff -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 | |
| 50 | diff -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). |
| 62 | diff -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) -> |
| 74 | diff -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 | + []. |