<div class="gmail_quote">2011/9/26 Motiejus Jakštys <span dir="ltr"><<a href="mailto:desired.mta@gmail.com">desired.mta@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5">On Mon, Sep 26, 2011 at 17:28, Jonas Boberg<br>
<<a href="mailto:jonas.boberg@nomasystems.com">jonas.boberg@nomasystems.com</a>> wrote:<br>
> Hi,<br>
><br>
> We solve this by having a parse transformation that adds additional<br>
> functions to the module (at compile time). More specifically, we use<br>
> this to generate functions that serialize and deserialize json objects<br>
> to records, including type verification based on the spec annotations.<br>
<br>
</div></div>Hi,<br>
<br>
is this hosted somewhere?<br>
<font color="#888888"><br>
Motiejus Jakštys<br>
</font></blockquote></div><br><div>Hi all,</div><div><br></div><div>Thanks for the responses - I'll answer a few questions and clarify. I should have worded this question "getting type info from beam code compiled without debug_info" instead. I'd like to be able to get the -spec info for several reasons:</div>
<div><br></div><div>1. Discovery - think hoogle for Erlang packages</div><div>2. Static Analysis</div><div>3. Instrumentation</div><div><br></div><div>The idea of searching based on type information has come up on the list before. Item (2) is obvious, and tools like dialyzer and QuickCheck/PropEr are already using this type information to great effect. I just haven't figured out how to unpick what they're doing properly. </div>
<div><br></div><div>As for (3), there are amazing capabilities built into erlang thanks to the tracing capabilities in erts. I'm using these for diagnostic purposes, but I don't see them as something that I'd like to have *always on* in my production code. There are limitations to using a tracer process and of course writing to a file or socket is safe(er) but there are limited guarantees about what gets delivered and ordering and so on. Tracing feels to me like something I turn on for diagnostic purposes. The kind of instrumentation I'm after is more akin to something AOP, where I want to get the build system to do some work for me but keep a tight control of what code gets generated as it is now a proper part of my application.</div>
<div><br></div><div>The kind of post processing on the beam code I'd like to do might insert things like logging statements or increment lightweight performance counters. I'd like to do this as part of my build, so that I can </div>
<div><br></div><div>(a) pretty print the beam (using erl_pp) if I want to see what's been added</div><div>(b) make sure that the instrumented code is what gets unit/integration/load tested</div><div> </div><div>In order to apply these modifications to my own source code, I can use a parse_transform and that's easy enough. I'd also like to have a declarative approach for defining where the instrumentation/code-weaving takes place, and type signatures seem like a good candidate for this. Let's say I want to put a performance counter around calls to any function in any module which has a name ending in _db, taking a #'myapp.query'{} record and an opaque connection_handle() type. I might define the target operations (in my own source code which is to be instrumented) by saying something like:</div>
<div><br></div><div>around('call(*_log:*(#'myapp.query'{}, connection_handle()))', Handler) </div><div>%% where Handler is an {M,F,A} or callback module conforming to a simple API</div><div><br></div><div>
Now I suppose this is somewhat akin to a match specification {'_', '_', ...} with some fancy stuff to handle the arguments such as {['$1', '$1', '$1'], [{is_record, '$1', 'myapp.query', record_info(size, 'myapp.query')}], ....</div>
<div><br></div><div>So maybe match specifications would make a better language, but they are a bit hard to follow (no offense to the good OTP folks intended) and type specifications with wildcards for naming (modules and functions) seem a bit simpler to me, at least for my purposes.</div>
<div><br></div><div>Now I *might* want to put a performance counter and/or logging statement (or whatever) around calls to _someone else's code_ such as calls to mochiweb_request or whatever, which I may not have the sources for and which may not have been compiled with debug_info (or used the "abstract_code" parse transform that's floating around). In those cases, it would be really nice if the compiler would keep hold of the type signatures in the beam, even when the abstract code isn't present. Of course in the meanwhile, if the abstract code is present I can get it out using beam_lib, but the clever people who wrote dialyzer/QuickCheck/PropEr must have solved this already. </div>
<div><br></div><div>So I'm wondering whether</div><div><br></div><div>1. The type introspection code it could be "unpicked" from these tools easily - I will need pointing in the right direction though!</div>
<div>2. The compiler should preserve type information in the generated beam, and if so is this in any roadmap or is a contribution the way to go?</div><div>3. Have I got the wrong impression of the trace facility or not</div>
<div><br></div><div>I see some kind of "type server" in both PropEr and Dialyzer and I'm pretty sure if this was abstracted out into a separate component that it could nicely form the core of a erlang-search web service or something of that ilk.</div>
<div><br></div><div>I'd also be interested in this code you've mentioned Jonas, if it is open source. For matching type specifications against modules/functions in other people's code however, a parse_transform isn't what I need.</div>
<div><br></div><div>Please do call out better approaches if you have them, but also bare in mind this is a mainly fun/educational exercise at the moment!</div><div><br></div><div>Cheers,</div><div><br></div><div>Tim</div>