[erlang-questions] Reassigning variables
mats cronqvist
masse@REDACTED
Thu Mar 19 13:22:31 CET 2009
Matthew Dempsky <matthew@REDACTED> writes:
> Here's an actual block of code from the Erlang compiler:
>
> lc_tq(Line, E, [{generate,Lg,P,G}|Qs0], Mc, St0) ->
> {Gs,Qs1} = splitwith(fun is_guard_test/1, Qs0),
> {Name,St1} = new_fun_name("lc", St0),
> {Head,St2} = new_var(St1),
> {Tname,St3} = new_var_name(St2),
> LA = lineno_anno(Line, St2),
> LAnno = #a{anno=LA},
> Tail = #c_var{anno=LA,name=Tname},
> {Arg,St4} = new_var(St3),
> {Nc,[],St5} = expr({call,Lg,{atom,Lg,Name},[{var,Lg,Tname}]}, St4),
> {Guardc,St6} = lc_guard_tests(Gs, St5), %These are always flat!
> {Lc,Lps,St7} = lc_tq(Line, E, Qs1, Nc, St6),
> {Pc,St8} = list_gen_pattern(P, Line, St7),
> {Gc,Gps,St9} = safe(G, St8), %Will be a
> function argument!
> Fc = function_clause([Arg], LA, {Name,1}),
> ....
how about this then.
my_expr(Lg,Name,Tname,St) ->
expr({call,Lg,{atom,Lg,Name},[{var,Lg,Tname}]},St).
my_lanno(Line,Tname,St) ->
LA = lineno_anno(Line,St),
{LA,#a{anno=LA},#c_var{anno=LA,name=Tname}}.
my_lc_tq(Line, E, [{generate,Lg,P,G}|Qs], Mc, St) ->
all(s(qs,st,{Qs,St}),
[fun(X)->s(X,gs,qs1, splitwith(fun is_guard_test/1,f(X,qs)))end
,fun(X)->s(X,name,st, new_fun_name("lc", f(X,St)))end
,fun(X)->s(X,head,st, new_var(f(X,st)))end
,fun(X)->s(X,tname,st, new_var_name(f(X,st)))end
,fun(X)->s(X,la,lanno,tail,my_lanno(Line,f(X,tname),f(X,st)))end
,fun(X)->s(X,arg,st, new_var(f(X,st)))end
,fun(X)->s(X,nc,'',st, my_expr(Lg,f(X,name),f(X,tname),f(X,st)))end
,fun(X)->s(X,guardc,st, lc_guard_tests(f(X,gs),f(X,st)))end
,fun(X)->s(X,lc,lps,st, lc_tq(Line,E,f(X,qs),f(X,nc),f(X,st)))end
,fun(X)->s(X,pc,st, list_gen_pattern(P,Line,f(X,st)))end
,fun(X)->s(X,gc,gps,st, safe(G,f(X,st)))end
,fun(X)->s(X,fc,function_clause([f(X,arg)],f(X,la),{f(X,name),1}))end]).
slightly longer (15 vs. 19 lines) and it needs the (trivial) helper
functions s(tore), f(etch) and all. But a heck of a lot easier to
maintain and extend(*).
I guess you could turn the fun(X)->s(X,...)end boilerplate into a
macro(**), but I'm not sure that actually improves things.
mats
(*) At least I think so. Of course, I also think the original is an
abomination. Shows what I know.
(**) like this;
-define(S(X,Ts,Xp), fun(X)->s(X,Ts,Xp)end).
my_lc_tq(Line, E, [{generate,Lg,P,G}|Qs], Mc, St) ->
all(s(qs,st,{Qs,St}),
[?S(X,{gs,qs1}, splitwith(fun is_guard_test/1,f(X,qs)))
,?S(X,{name,st}, new_fun_name("lc", f(X,St)))
,?S(X,{head,st}, new_var(f(X,st)))
,?S(X,{tname,st}, new_var_name(f(X,st)))
,?S(X,{la,lan,tail},my_lanno(Line,f(X,tname),f(X,st)))
,?S(X,{arg,st}, new_var(f(X,st)))
,?S(X,{nc,'',st}, my_expr(Lg,f(X,name),f(X,tname),f(X,st)))
,?S(X,{guardc,st}, lc_guard_tests(f(X,gs),f(X,st)))
,?S(X,{lc,lps,st}, lc_tq(Line,E,f(X,qs),f(X,nc),f(X,st)))
,?S(X,{pc,st}, list_gen_pattern(P,Line,f(X,st)))
,?S(X,{gc,gps,st}, safe(G,f(X,st)))
,?S(X,{fc}, function_clause([f(X,arg)],f(X,la),{f(X,name),1}))]).
More information about the erlang-questions
mailing list