[erlang-questions] better ct_expand and some intricate problems

9 views
Skip to first unread message

Ulf Wiger

unread,
Jan 28, 2012, 11:09:39 AM1/28/12
to erlang-questions Questions

I have made some improvements to ct_expand


It used to be that it could only expand simple expressions. Now, it can handle calls to local functions, which are then interpreted. It also handles things like fun foo/1, by fetching the function definition and inlining it as a "regular" fun.

Unfortunately, I failed to bring it up to the level that I aspired to, namely to improve some of Tony Rogvall's code (not yet released). The problem there was that his code called functions that stored funs in a dict. Doing this at compile-time, the funs would - at best - end up being interpreted. As it was, I didn't even get that far, since funs created by one interpreted function couldn't be passed as arguments to another interpreted function.

The culprits are erl_eval, which unconditionally converts the return values into regular terms, and erl_parse:abstract/1, which fails to create abstract expressions from funs. Thus, the conversion to regular terms is not reversible in this case.

In https://github.com/uwiger/parse_trans/blob/master/examples/ct_expand_test.erl#L15, an example is given of what kind of things can now be done with ct_expand.

I added a trace option, so that it would be easier to debug complex expansions:

Eshell V5.8.4  (abort with ^G)
1> c(ct_expand_test,[{ct_expand_trace,[r]}]).
ct_expand (27): call zip([1,2],[a,b])
ct_expand (27): call zip([2],[b])
ct_expand (27): call zip([],[])
ct_expand (27): returned from zip/2: []
ct_expand (27): returned from zip/2: [{{2},{b}}]
ct_expand (27): returned from zip/2: [{{1},{a}},{{2},{b}}]
Pretty-printed in "./ct_expand_test.xfm"

(Not perfect: the functions that were inlined don't show up in the trace.)

I welcome ideas on how to get around the above limitation with reasonable effort (I know I could make my own evaluator, but that seems like too high a price).

Oh, the error reporting from parse_trans has been greatly improved. It now detects parse_errors immediately, and aborts the transform, and also reports transform errors in a less noisy way. Let me know if you have issues with it.

BR,
Ulf W


Ulf Wiger

unread,
Jan 28, 2012, 12:39:52 PM1/28/12
to erlang-questions Questions

Never mind - problem solved. Funs from erl_eval _can_ actually be abstracted using erl_eval:fun_data/1.

Too bad erl_parse:abstract/1 isn't aware of that…

As it happens, since the resulting data structure is in abstract form, funs in a dict will be compiled eventually anyway. :)

I leave it to you all to find remaining limitations or exciting uses.

BR,
Ulf W

_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Vance Shipley

unread,
Jan 29, 2012, 4:08:42 PM1/29/12
to Ulf Wiger, erlang-questions Questions
On Sat, Jan 28, 2012 at 06:39:52PM +0100, Ulf Wiger wrote:
} Funs from erl_eval _can_ actually be abstracted using erl_eval:fun_data/1.
}
} Too bad erl_parse:abstract/1 isn't aware of that…

Indeed. Neither is the Erlang Pretty Printer. Not without converting
the fun_data to the proper abstract expression form for a fun():

1> {ok, Tokens, _} = erl_scan:string("fun () -> ok end."),
1> {ok, ExprList} = erl_parse:parse_exprs(Tokens),
1> {value, Fun, _} = erl_eval:exprs(ExprList, []),
1> {fun_data, _, Clauses} = erl_eval:fun_data(Fun),
1> AbsExpr = {'fun', 0, {clauses, Clauses}},
1> io:put_chars(erl_pp:expr(AbsExpr)).
fun() ->
ok
endok


--
-Vance

Reply all
Reply to author
Forward
0 new messages