Discussion:
How to get the line number of current executable code?
(too old to reply)
unknown
2008-08-15 17:03:08 UTC
Permalink
HI:

I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....

the above code will print the line number of the calling point in the source
file.

How can I do this in erlang?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080816/e4920188/attachment.html>
unknown
2008-08-15 18:22:54 UTC
Permalink
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the source
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])

/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-15 18:31:42 UTC
Permalink
Thanks.

How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the
source
Post by unknown
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080816/91393615/attachment.html>
unknown
2008-08-15 19:05:08 UTC
Permalink
Post by unknown
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
There is currently no support for that in Erlang.

/Richard
unknown
2008-08-16 16:40:08 UTC
Permalink
Hi Richard,

How about if I compiled the source with debugging enabled? Isn't this
information supposed to be there (along with function name and other
info)?

/Ahmed Al-Issaei
Post by unknown
Post by unknown
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
There is currently no support for that in Erlang.
/Richard
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-16 18:19:12 UTC
Permalink
Post by unknown
Hi Richard,
How about if I compiled the source with debugging enabled? Isn't this
information supposed to be there (along with function name and other
info)?
The problem is that there is no direct line-for-line mapping between the
abstract code in the debugging information, and the executing beam code.
The beam code does contain the info about the current function, but no
line numbers. Using a combination of the two, you could find the line
number for the current function, but figuring out the actual line
within that function (given the current point in the beam code) could
only be approximated using heuristics.

If you're actually running in interpreted mode (debugging mode), you
do get the current line, but it's a couple of orders of magmitude
slower, so you don't want to do that for all your code.

I hope some day someone will find the time to make the compiler
propagate the line number information into a mapping table that could
be included in the beam file at all times, even if the file was not
compiled with debugging enabled. That would make it possible to give
much nicer stacktraces.

/Richard
unknown
2008-08-16 19:41:01 UTC
Permalink
Post by unknown
If you're actually running in interpreted mode (debugging mode), you
do get the current line, but it's a couple of orders of magmitude
slower, so you don't want to do that for all your code.
How do I run the vm in debugging mode?

In the AST transformation code for my pet lisp frontend, it's often
hard to tell where a pattern match failed, b/c there can be many
matches within a single function.

It would be /very/ helpful if running in debugging mode gives me the
line #. I can live with performance penalty at development time...
unknown
2008-08-17 08:37:10 UTC
Permalink
Post by unknown
How do I run the vm in debugging mode?
Not the vm as such, more like a meta-interpreter:

http://www.erlang.org/doc/apps/debugger/index.html

/Richard
unknown
2008-08-15 19:07:49 UTC
Permalink
You should trust the macro. It must use a similar method to Python's because
they are both compiled to bytecode and thus there wouldn't *really* be line
numbers in either one.

2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the
source
Post by unknown
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080815/a74e8576/attachment.html>
unknown
2008-08-15 20:29:50 UTC
Permalink
Something I've wished for in numerous languages over the years is a macro
that expands to the current function, something like ?MODULE. I don't
suppose there is one lurking somewhere in Erlang...?

2008/8/15 Matt Williamson <dawsdesign>
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't *really*
be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the
source
Post by unknown
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080815/573d37e0/attachment.html>
unknown
2008-08-15 21:06:56 UTC
Permalink
Why sure, you just do this:

-module(m).
-export([f/0]).

-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).

f() ->
{current_function, ?FUNCTION}.



Eshell V5.5.4 (abort with ^G)
1> c(m).
{ok,m}
2> m:f().
{current_function,{m,f,0}}
3>

BR,
Ulf W ;-)
Post by unknown
Something I've wished for in numerous languages over the years is a macro
that expands to the current function, something like ?MODULE. I don't
suppose there is one lurking somewhere in Erlang...?
2008/8/15 Matt Williamson <dawsdesign>
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't *really*
be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the source
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-15 21:48:27 UTC
Permalink
How cool is that?! Thanks!
Post by unknown
-module(m).
-export([f/0]).
-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).
f() ->
{current_function, ?FUNCTION}.
Eshell V5.5.4 (abort with ^G)
1> c(m).
{ok,m}
2> m:f().
{current_function,{m,f,0}}
3>
BR,
Ulf W ;-)
Post by unknown
Something I've wished for in numerous languages over the years is a macro
that expands to the current function, something like ?MODULE. I don't
suppose there is one lurking somewhere in Erlang...?
2008/8/15 Matt Williamson <dawsdesign>
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't
*really*
Post by unknown
Post by unknown
be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in
the
Post by unknown
Post by unknown
Post by unknown
Post by unknown
Post by unknown
source
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080815/c18eaa8c/attachment.html>
unknown
2008-08-16 17:59:08 UTC
Permalink
Ulf,

On second thoughts, although that IS very cool, it would likely be very
expensive because it generates and catches an exception. This would matter
if it is used to do a lot of logging (which is what I would use it for).
What I really would like is a compile-time constant (pre-processor macro). I
suppose one could hack epp...?

Ed
Post by unknown
-module(m).
-export([f/0]).
-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).
f() ->
{current_function, ?FUNCTION}.
Eshell V5.5.4 (abort with ^G)
1> c(m).
{ok,m}
2> m:f().
{current_function,{m,f,0}}
3>
BR,
Ulf W ;-)
Post by unknown
Something I've wished for in numerous languages over the years is a macro
that expands to the current function, something like ?MODULE. I don't
suppose there is one lurking somewhere in Erlang...?
2008/8/15 Matt Williamson <dawsdesign>
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't
*really*
Post by unknown
Post by unknown
be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in
the
Post by unknown
Post by unknown
Post by unknown
Post by unknown
Post by unknown
source
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080816/1bf299b5/attachment.html>
unknown
2008-08-16 18:22:22 UTC
Permalink
Post by unknown
On second thoughts, although that IS very cool, it would likely be very
expensive because it generates and catches an exception. This would
matter if it is used to do a lot of logging (which is what I would use
it for). What I really would like is a compile-time constant
(pre-processor macro). I suppose one could hack epp...?
Don't worry about that. Exception handling is not particularly
expensive in Erlang. (Certainly not compared to the work of logging.)

/Richard
unknown
2008-08-17 09:19:44 UTC
Permalink
I should perhaps bring special notation to the smiley at the
end of my message. (:

Whether or not the solution is cool is surely a matter of
taste - but I believe that the one who first came up with it
was Mats Cronqvist, the champion of obfuscated Erlang
code. (:

I'm not sure about *very* expensive. The exception mechanism
isn't that heavyweight. At least in the past, there were issues
with HiPE, in that exceptions in native code would generate an
empty stack trace. I vaguely recall that being fixed now.

I agree that a compile-time constant would be much preferred.

BR,
Ulf W
Post by unknown
Ulf,
On second thoughts, although that IS very cool, it would likely be very
expensive because it generates and catches an exception. This would matter
if it is used to do a lot of logging (which is what I would use it for).
What I really would like is a compile-time constant (pre-processor macro). I
suppose one could hack epp...?
Ed
Post by unknown
-module(m).
-export([f/0]).
-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).
f() ->
{current_function, ?FUNCTION}.
Eshell V5.5.4 (abort with ^G)
1> c(m).
{ok,m}
2> m:f().
{current_function,{m,f,0}}
3>
BR,
Ulf W ;-)
Post by unknown
Something I've wished for in numerous languages over the years is a macro
that expands to the current function, something like ?MODULE. I don't
suppose there is one lurking somewhere in Erlang...?
2008/8/15 Matt Williamson <dawsdesign>
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't *really*
be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Post by unknown
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
Post by unknown
I want to implement a function like "get_current_lineno()/0" to get the
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in the
source
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
--
For every expert there is an equal and opposite expert - Arthur C. Clarke
unknown
2008-08-18 14:00:35 UTC
Permalink
Post by unknown
-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).
A safer solution (it has no side effects, unlike the above):

-define(FUNCTION,element(2,process_info(self(),current_function))).

I don't know if it's more expensive or not, but if it does matter,
you're doing something wrong.

Georgy
unknown
2008-08-25 06:57:44 UTC
Permalink
Post by unknown
I should perhaps bring special notation to the smiley at the
Whether or not the solution is cool is surely a matter of
taste - but I believe that the one who first came up with it
was Mats Cronqvist, the champion of obfuscated Erlang
thanks for the endorsement...

for the record, i have since moved on to using this:
-define(position,[process_info(self(),current_function),{line,?LINE}]).

sometimes adding this:
proplists:lookup(source,?MODULE:module_info(compile)).

mats
unknown
2008-08-25 23:34:26 UTC
Permalink
Hi All,

This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?

Best regards,

Ahmed Al-Issaei

On Mon, Aug 25, 2008 at 10:57 AM, Mats Cronqvist
Post by unknown
Post by unknown
I should perhaps bring special notation to the smiley at the
Whether or not the solution is cool is surely a matter of
taste - but I believe that the one who first came up with it
was Mats Cronqvist, the champion of obfuscated Erlang
thanks for the endorsement...
-define(position,[process_info(self(),current_function),{line,?LINE}]).
proplists:lookup(source,?MODULE:module_info(compile)).
mats
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-26 06:58:08 UTC
Permalink
Post by unknown
Hi All,
This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?
The only way of doing that is to force an exception, and then look
at the stack trace. Something like this:

Trace = try throw(oops) catch oops -> erlang:get_stacktrace() end

However, due to tail call optimization in Erlang, you will not see
any functions in the list that were visited on the way but were exited
through a tail call.

/Richard
unknown
2008-08-26 08:54:50 UTC
Permalink
Post by unknown
Post by unknown
Hi All,
This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?
The only way of doing that is to force an exception, and then look
at the stack trace.
there is no way to reliably get the name of the calling function.
it is true that the stack sometimes contain the name of the calling
function.
it is not true that the only way to inspect the stack is by forcing an
exception.

i'm too lazy to write actual code, but try this in the shell;

(r12)41> {_,BT}=erlang:process_info(self(),backtrace).
(r12)42> S=fun(B,{_,[_,{F,L}|_]})->
<<_:F/binary,R:L/binary,_/binary>> =B, R end.
(r12)43> S(BT,re:run(BT,"Return addr\\s[0-9a-z]+\\s\\(([^\\s]*)")).
<<"erl_eval:expr/5">>

clear as the day!

mats
unknown
2008-08-26 09:15:38 UTC
Permalink
Post by unknown
it is not true that the only way to inspect the stack is by forcing an
exception.
i'm too lazy to write actual code, but try this in the shell;
(r12)41> {_,BT}=erlang:process_info(self(),backtrace).
(r12)42> S=fun(B,{_,[_,{F,L}|_]})->
<<_:F/binary,R:L/binary,_/binary>> =B, R end.
(r12)43> S(BT,re:run(BT,"Return
addr\\s[0-9a-z]+\\s\\(([^\\s]*)")).
<<"erl_eval:expr/5">>
Ugh! I didn't know that flag to process_info existed, but I'm happy to
see that Mats' talent for sniffing out the dark corners of Erlang and
using them for unspeakable deeds is as strong as ever.

/Richard
unknown
2008-08-26 19:05:10 UTC
Permalink
Hi Mats,

I've seen process_display(Pid, backtrace) but never thought to use it
this way. Thanks for the insight.

Best regards,

Ahmed Al-Issaei

On Tue, Aug 26, 2008 at 12:54 PM, Mats Cronqvist
Post by unknown
Post by unknown
Post by unknown
Hi All,
This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?
The only way of doing that is to force an exception, and then look
at the stack trace.
there is no way to reliably get the name of the calling function.
it is true that the stack sometimes contain the name of the calling
function.
it is not true that the only way to inspect the stack is by forcing an
exception.
i'm too lazy to write actual code, but try this in the shell;
(r12)41> {_,BT}=erlang:process_info(self(),backtrace).
(r12)42> S=fun(B,{_,[_,{F,L}|_]})->
<<_:F/binary,R:L/binary,_/binary>> =B, R end.
(r12)43> S(BT,re:run(BT,"Return addr\\s[0-9a-z]+\\s\\(([^\\s]*)")).
<<"erl_eval:expr/5">>
clear as the day!
mats
unknown
2008-08-26 06:58:22 UTC
Permalink
Greetings,

Building upon the suggestion made by Ulf Wiger this would probably work
(possible reasons for not working includes, but are not limited to, tail
calls):
-define(FUNCTION_THAT_CALLED, lists:nth(2, element(2,element(2,catch
erlang:error([]))))).


bengt
Post by unknown
Hi All,
This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?
Best regards,
Ahmed Al-Issaei
On Mon, Aug 25, 2008 at 10:57 AM, Mats Cronqvist
Post by unknown
Post by unknown
I should perhaps bring special notation to the smiley at the
Whether or not the solution is cool is surely a matter of
taste - but I believe that the one who first came up with it
was Mats Cronqvist, the champion of obfuscated Erlang
thanks for the endorsement...
-define(position,[process_info(self(),current_function),{line,?LINE}]).
proplists:lookup(source,?MODULE:module_info(compile)).
mats
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-15 20:35:45 UTC
Permalink
Many languages are compiled to byte code, but able to recover line
numbers at run time. I assume they annotate the byte codes with file
and line information. Note that this is more powerful than the Erlang
macros. For example, Perl's caller() function allows you to inspect
the full call stack in this way.


-kevin
Post by unknown
You should trust the macro. It must use a similar method to Python's
because they are both compiled to bytecode and thus there wouldn't
*really* be line numbers in either one.
2008/8/15 devdoer bird <devdoer2>
Thanks.
How can I do this without macro? I know python supply some tools to
determine the line number in run time,like inspect module.
Post by unknown
I want to implement a function like "get_current_lineno()/0" to
get the
Post by unknown
current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
the above code will print the line number of the calling point in
the source
Post by unknown
file.
How can I do this in erlang?
There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])
/Anders
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-18 00:46:15 UTC
Permalink
Post by unknown
Many languages are compiled to byte code, but able to recover line
numbers at run time. I assume they annotate the byte codes with file
and line information. Note that this is more powerful than the Erlang
macros. For example, Perl's caller() function allows you to inspect
the full call stack in this way.
There is a tradeoff.
When your compiler does good stuff like constant propagation,
inlining, loop unrolling, loop fusion, &c, it gets hard to make
'the line number' mean anything. For example, suppose we had

Ns = [sum(L) || L <- Ls],
Ds = [length(L) || L <- Ls],
Aves = [N/D || {N,D} <- lists:zip(Ns, Ds)]

This is the kind of thing the GHC compiler eats for lunch;
assuming Ns and Ds are not used anywhere else it turns into
the equivalent of

Aves = [sum(L)/length(L) || L <- Ls]

Which line does this correspond to? ALL of them.
(Actually, I believe GHC will take this a stage further, and inline
and fuse the sum and length loops as well. In which case we have
code within a single "line" coming from several files.)

The Erlang compiler isn't that smart. (Yet. A man can dream.)

One of the reasons that Perl can give you line numbers is that
Perl is to speed what a spent match is to illumination.

Debugging information can be bulky.
For a non-Erlang example, I tried a small Java file.
It has 172 lines, 116 of which count as SLOC.
javac -g:none Calls.java => 2583 bytes
javac Calls.java => 3035 bytes; 452 bytes of line#
javac -g Calls.java => 3283 bytes; 248 bytes of other stuff
The Java compiler counted 96 lines it thought worth recording,
so that's 4.71 bytes per line. (Clearly they are not bothering
to compress this much.) There are about 1380 bytes of actual code,
so the line number table is about 1/3 as big as the code.

Even assuming that virtual memory is huge and close to free,
line number information should be used rarely enough that you
don't want to mix it in with the instructions; you want to
segregate it somewhere else.

The really interesting thing is that javap basically lists the
line number mappings backwards. Instead of saying "block [a..z)
of byte code corresponds to line L", it says "line L corresponds
to byte code starting at x". This suggests a fairly, um,
direct mapping from source code to byte code: inlining,
loop fusion, loop unrolling, &c are left to the JIT.

Now the Erlang compiler isn't as smart as GHC, but it _is_
smarter than that. With inlining and tail recursion optimisation,
even the stack trace isn't what it seems.

A rather long-winded way of saying TANSTAAFL, I suppose.
unknown
2008-08-18 12:59:18 UTC
Permalink
2008/8/18 Richard A. O'Keefe <ok>
Post by unknown
There is a tradeoff.
When your compiler does good stuff like constant propagation,
inlining, loop unrolling, loop fusion, &c, it gets hard to make
'the line number' mean anything. For example, suppose we had
Ns = [sum(L) || L <- Ls],
Ds = [length(L) || L <- Ls],
Aves = [N/D || {N,D} <- lists:zip(Ns, Ds)]
This is the kind of thing the GHC compiler eats for lunch;
assuming Ns and Ds are not used anywhere else it turns into
the equivalent of
Aves = [sum(L)/length(L) || L <- Ls]
Which line does this correspond to? ALL of them.
(Actually, I believe GHC will take this a stage further, and inline
and fuse the sum and length loops as well. In which case we have
code within a single "line" coming from several files.)
The Erlang compiler isn't that smart. (Yet. A man can dream.)
One problem Erlang would have doing this type of optimisation, which would
be wonderful to have, is the handling of side effects and errors. That type
of aggressive inlining and fusing would change the order in which side
effects occur which means that the code would not be equivalent. Similar for
errors. Haskell, being side-effect free, does not have this problem.

Robert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080818/41fd6265/attachment.html>
unknown
2008-08-19 00:53:23 UTC
Permalink
Post by unknown
The Erlang compiler isn't that smart. (Yet. A man can dream.)
One problem Erlang would have doing this type of optimisation, which
would be wonderful to have, is the handling of side effects and
errors.
I have also dreamed of a
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure, and a promise that if
any exception would be raised in a call to such a function it would
not matter which exception.

However, that seemed off topic.

--
If stupidity were a crime, who'd 'scape hanging?
unknown
2008-08-19 15:39:22 UTC
Permalink
Post by unknown
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure
What happens if a pure function calls a function that is not pure?

I mean, the compiler just can't check it. Of course it can check local
functions, but a function in another module can not be trusted. It
might be pure at the time of compilation, but it might be impure in its
next version.

It could only be checked in runtime, throwing an exception whenever an
impure function is called from a pure one.

Georgy
unknown
2008-08-19 16:59:47 UTC
Permalink
Post by unknown
Post by unknown
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure
What happens if a pure function calls a function that is not pure?
I mean, the compiler just can't check it. Of course it can check local
functions, but a function in another module can not be trusted. It
might be pure at the time of compilation, but it might be impure in its
next version.
Yes, so cross-module calls cannot be allowed in a pure function,
at least unless we find a way to statically group modules together.

BR,
Ulf W
unknown
2008-08-20 05:44:33 UTC
Permalink
Post by unknown
Post by unknown
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure
What happens if a pure function calls a function that is not pure?
I mean, the compiler just can't check it.
Yes it can. That's the whole POINT of -pure declarations.
The NU Prolog system *could* and *did* check this.
Post by unknown
Of course it can check local
functions, but a function in another module can not be trusted.
Cannot be trusted? Sure it can. You haven't seen a complete
proposal, because I have other maddened grizzly bears to stun,
but the idea is that
- the meta-data for a module records which exported functions are
pure and which are not
- when the compiler notes a pure function calling a function
from another module, it records a dependency on that function
being exported as pure
- when a module is loaded, the run time system checks that
every function it tries to import as pure from some other
module IS pure if that module is already loaded,
every module that depends on this one exporting some
function(s) as pure is satisfied.
If either check fails, the module is not loaded.

This takes care of the "another module" issue.
The tricky one is higher order functions.
I actually came up with this idea back shortly before
'funs' were added to the language, and dropped it when they
came in. There are basically two ways out: one is to say
that a pure function can't be or call a higher order function,
and the other is to use some sort of type system.
unknown
2008-08-21 10:16:23 UTC
Permalink
Post by unknown
- the meta-data for a module records which exported functions are
pure and which are not
- when the compiler notes a pure function calling a function
from another module, it records a dependency on that function
being exported as pure
- when a module is loaded, the run time system checks that
every function it tries to import as pure from some other
module IS pure if that module is already loaded,
every module that depends on this one exporting some
function(s) as pure is satisfied.
If either check fails, the module is not loaded.
This is completely against current Erlang practice.

Currently if a module A uses module B, noone checks if B contains the
used functions or not. Neither at compile time, nor at module load
time. I think because the check would make module upgrades way more
difficult.

Think about a module B using a function AF from module A. In the next
version of the modules, the function A:AF is removed and B is not using
it any more. Currently you just load the two modules. In the presence
of a load-time check, you'd have to load module B first, then A. No
problem here.

Now think about a module A using B's BF and B using A's AF. When both
functions are removed, there is no legal upgrade order.

The same problem exists with checked pure functions. Module A using B's
pure BF (and expects it to be pure), and B using A's pure AF (and
expects it to be pure). In the next version both the functions switch
to impure, together with their consumers. There is no legal upgrade
order :-(

There probably are solutions (simultaneous atomic loading of several
modules? using extra transition module versions to make the upgrade
possible?), but current module upgrading technology/practice must
change radically.

Georgy
unknown
2008-08-22 04:34:08 UTC
Permalink
Post by unknown
Post by unknown
- the meta-data for a module records which exported functions are
pure and which are not
- when the compiler notes a pure function calling a function
from another module, it records a dependency on that function
being exported as pure
- when a module is loaded, the run time system checks that
every function it tries to import as pure from some other
module IS pure if that module is already loaded,
every module that depends on this one exporting some
function(s) as pure is satisfied.
If either check fails, the module is not loaded.
This is completely against current Erlang practice.
(a) That's a very misleading way to put it.

It would only be "against" if it in some way opposed or prevented
the kinds of things people are doing.

Erlang *happens* not to check very much, but this is hardly a
core design principle.

(b) IT DOESN'T MATTER!
For heaven's sake, I was answering a question about an idea I had
more than ten years ago, which was abandoned when Erlang got
'funs'.
Post by unknown
Currently if a module A uses module B, noone checks if B contains the
used functions or not. Neither at compile time, nor at module load
time. I think because the check would make module upgrades way more
difficult.
First off, you can't do it at compile time because you do not know
*which* module called B, or which version of that module, A will
eventually
be loaded with. That's why it needs to be a load time conversion.

Second, haven't we all heard enough about "Version Skew" and "DLL Hell"
over the last N years to convince us that making it as easy as possible
for people to shoot themselves in the foot is not always a Good Thing?

If you have two loaded modules, A and B, and A uses something that B
provides, and you replace B with a B' that does not provide that any
more, what you have done is NOT an upgrade. What you have done is to
convert a working system into a non-working system. If you have a
new A' that doesn't need that service from B', then either you need
to change A to A' first, or you need to replace both modules *together*.


Just at the moment I am vey hot under the collar about "upgrades".
Here's my story:

I have a Macintosh on my desk.

I have to teach 5 introductory programming lectures to
first year surveyors. The surveying department insisted
on Visual Basic as the programming language. Since their
students will mostly be making minor additions to Excel
spreadsheets, this almost makes sense.

Fortunately, Excel is part of Microsoft Office for the Mac,
and last year I was able to develop examples using VBA in
Excel on my Mac.

This year the system administrators installed Microsoft
Office 2008 for Macintosh on my machine.

It wasn't until I tried revising my materials for SURV112
that I discovered that Office 2008 does not include VBA
any more. Gone. Vanished. All Office 2008 can do with
VBA macros is offer to delete them. We're supposed to
use AppleScript instead.

I've taken the trouble to learn AppleScript, and it is
certainly integrated with MacOS in a way that VBA never
was.

None-the-less, I am ***HOPPING MAD*** that nobody told
me when the "upgrade" was done "Oh, by the way, this is
going to remove a feature you need for your work; do
you really want it?"

If my configuration is inconsistent, I d--n well *WANT* to be
told about it before the damage is done.

I am not arguing against hot loading.
What I don't like is *silently* moving to an inconsistent state
or a state where functionality I rely on is missing.

(I've also lost the ability to print slides, because Acrobat 8
has this weird bug where slide pages after the first are mirror-
imaged, and the sysadmins were terrified at the thought of the
trouble they've have trying to replace it with an older version.
Hopefully Acrobat 9, which they've now installed, fixes this...)
Post by unknown
Now think about a module A using B's BF and B using A's AF. When both
functions are removed, there is no legal upgrade order.
Yes there is. It's A+B *together.
I am not saying that this is supported *now*,
but it could be, and it should be.
And for the "block compilation" that people keep mentioning,
it will *have* to be, for this very reason.

You see, when you say "there is no legal upgrade order",
what that *really* means is that "if you replace modules one
at a time, there can be unavoidable windows when the system
is in an inconsistent state, does not know that, and tries
to continue operations anyway." Does that sound like a good idea?


Anyrate, to repeat: this was *NOT* a current proposal,
otherwise it would have been an EEP, not an off-hand remark
in another thread, so it was pointless to criticise it.
unknown
2008-08-22 07:24:48 UTC
Permalink
Post by unknown
Post by unknown
Now think about a module A using B's BF and B using A's AF. When both
functions are removed, there is no legal upgrade order.
Yes there is. It's A+B *together.
I am not saying that this is supported *now*,
but it could be, and it should be.
And for the "block compilation" that people keep mentioning,
it will *have* to be, for this very reason.
You see, when you say "there is no legal upgrade order",
what that *really* means is that "if you replace modules one
at a time, there can be unavoidable windows when the system
is in an inconsistent state, does not know that, and tries
to continue operations anyway." Does that sound like a good idea?
I just want to point out, for the record, that the problem
is not completely unsolvable today. This is what the
OTP Release Handler does.

If you build your system using OTP mechanisms (gen_servers,
supervision trees, etc...) the release handler pauses
all processes (in their gen_servers) before upgrading all
modules belonging to an application, and then lets
them continue after the upgrade.

It is just not a language feature, and requires discipline.
:
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
unknown
2008-08-19 18:30:26 UTC
Permalink
Post by unknown
I have also dreamed of a
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure, and a promise that if
any exception would be raised in a call to such a function it would
not matter which exception.
For those of us not well-versed in NU Prolog, what is the benefit of this?
Please advise. Thank-you.

David
unknown
2008-08-19 18:50:12 UTC
Permalink
Post by unknown
Post by unknown
I have also dreamed of a
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure, and a promise that if
any exception would be raised in a call to such a function it would
not matter which exception.
For those of us not well-versed in NU Prolog, what is the benefit of this?
Please advise. Thank-you.
The compiler can perform optimizations which might otherwise not be
possible. For example, various sorts of loop fusion optimizations are
provably safe for pure functions.


-kevin
unknown
2008-08-20 05:59:49 UTC
Permalink
Post by unknown
For those of us not well-versed in NU Prolog, what is the benefit of
[-pure]
Post by unknown
this?
This was implicit in the original context:
"Haskell can do heavy duty optimisation that Erlang can't".
"Yes, but Haskell is pure, and Erlang isn't."
"Yes, but with functions declared to be -pure, Erlang
could do better than it does."
unknown
2008-08-17 10:01:32 UTC
Permalink
Post by unknown
On second thoughts, although that IS very cool, it would
likely be very
expensive because it generates and catches an exception.
This would matter
if it is used to do a lot of logging (which is what I would
use it for).
What I really would like is a compile-time constant
(pre-processor macro). I
suppose one could hack epp...?
The basic problem is that epp works on the token level, not the syntax tree level, so when you find ?FUNCTION there is no information about what function you're in. (And figuring it out seems like a thankless job.)

One possible hack: expand ?FUNCTION into something that can be recognized and replaced by a later pass. For instance:

1. In epp, replace ?FUNCTION by the syntax tree or tokens of a call to a made-up function, "erlang:current_function()", or some other unique well-known marker.

2. In sys_pre_expand, walk the syntax tree for each function M:F/N, and replace all occurrences of "erlang:current_function()" with {M, F, N}. (As part of expanding away records, etc.)

Occurrences of ?FUNCTION outside of functions will have to be handled too, e.g. by an error.

Best,
Thomas
unknown
2008-08-17 23:58:11 UTC
Permalink
Post by unknown
The basic problem is that epp works on the token level, not the
syntax tree level, so when you find ?FUNCTION there is no
information about what function you're in. (And figuring it out
seems like a thankless job.)
I note that while __FILE__, __LINE__, __DATE__, __TIME__ and so on are
macros in C, __func__ is not. It is a keyword. So the solution that
Thomas Lindgren proposes seems good. I would prefer one mechanism that
solves several issues, so I suggest that instead of ?FUNCTION the thing
to have is ?LOCATION
=> {File, Line, Module, Function, Arity, Clause_Number}
unknown
2008-08-17 09:51:37 UTC
Permalink
Post by unknown
In the AST transformation code for my pet lisp frontend,
it's often
hard to tell where a pattern match failed, b/c there can
be many
matches within a single function.
It would be /very/ helpful if running in debugging mode
gives me the
line #. I can live with performance penalty at development
time...
I'm not sure if this helps in your case, but if you're satisfied with getting line numbers in your exceptions, try smart_exceptions from jungerl. It's a parse transform, so it works without the debugger.

Best,
Thomas
unknown
2008-08-17 17:25:11 UTC
Permalink
Post by unknown
I'm not sure if this helps in your case, but if you're satisfied with getting line numbers in your exceptions, try smart_exceptions from jungerl. It's a parse transform, so it works without the debugger.
Ah, thanks for the pointer.

So you are basically providing a fall through case for M-F-A-line
error report whenever there's branching? It sounds like a good way to
do it.

I've read somebody (Joe?) saying that pattern matchings in erlang are
like mini contracts. Early failure from failed match is a good thing.
So I am wondering if Thomas's code transfomer is compatible with the
Erlang philosophy (I think it is). But I may be missing the obvious.

As mentioned, I am playing around with my pet lisp frontend. Having
seem Thomas's smart exception, it seems that it makes sense to provide
special syntatic support for matching failure. Something like,

(case X
<cases>*
: "expected such and such input")

The last line is a syntatic sugar for a universal pattern that throws
a {badmatch...}, but with M-F-A/line and reason. Ditto with function
clauses et al.

Robert V. probably wouldn't like it : )
Post by unknown
_______________________________________________
erlang-questions mailing list
erlang-questions
http://www.erlang.org/mailman/listinfo/erlang-questions
unknown
2008-08-17 12:14:24 UTC
Permalink
Post by unknown
I hope some day someone will find the time to make the
compiler
propagate the line number information into a mapping table
that could
be included in the beam file at all times, even if the file
was not
compiled with debugging enabled. That would make it
possible to give
much nicer stacktraces.
Indeed. Doing this might be a bit finicky but it's very helpful. The usual scripting language suspects already provide such stack traces, by the way.

Best,
Thomas
unknown
2008-08-17 19:48:18 UTC
Permalink
Post by unknown
So you are basically providing a fall through case for
M-F-A-line
error report whenever there's branching? It sounds like
a good way to
do it.
Basically the transform tries to "elaborate" all the places where an exception can be thrown into providing more information, and the program then throws the new exception when it's encountered. (There are a few cases where the transform misses out: undefined function calls and, I seem to recall, exceptions when building binaries, at the very least.)
Post by unknown
I've read somebody (Joe?) saying that pattern matchings
in erlang are
like mini contracts. Early failure from failed match is a
good thing.
So I am wondering if Thomas's code transfomer is
compatible with the
Erlang philosophy (I think it is). But I may be missing the
obvious.
All that basic smart_exceptions does is provide more information about the causes of an exception, so I don't think it's incompatible with such a principle. ("The basic transform", you ask? In principle, smart_exceptions also permits you to insert and run arbitrary code at the point of an exception, a bit like Common Lisp's condition handlers. But that's not tested much, and probably a bit too much complication.)

Best,
Thomas
Continue reading on narkive:
Loading...