www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Feature discussion: __traits(getSource, function)

reply Adam D. Ruppe <destructionator gmail.com> writes:
I have what might be a weird request here: a way to get the source code of a
function (or maybe class, etc. too) out of the compiler as a string literal.

Using existing features, I was able to think up a hacky solution: use
__FILE__, __LINE__, and string import to get the source and read it in. But my
implementation was bug riddled, needed extra code at the function, and relied
on conventions.

So I'd prefer something built in - a trait addition could do the job. I looked
at the compiler's source, and it doesn't seem to keep all the needed info
around, but I imagine it would be a lot easier for it to figure this out than
doing it with mixins.


Why would this be useful? My specific case is taking a D function and
translating it into javascript at run time, so I can print it out to the
browser and run it there too. (naturally, this requires some conventions and
simplifcation in the code to work anyway, so my hacky solution works for me).

Other advantages might be mixing it with string mixins to edit code at compile
time.


Honestly, I'm not sure about what else it would be good for. Can anyone think
of something compelling enough for me to dive into the dmd source and see
about doing it myself?

I started typing this excited about the possibilities, but I ended up changing
my mind while typing the short list of advantages... but let's discuss it. Any
ideas on how it would be useful?

Perhaps a simpler alternative would be __traits(sourceFile) and sourceLine -
to mimic my current solution.
Oct 15 2010
next sibling parent dennis luehring <dl.soluz gmx.net> writes:
Am 15.10.2010 18:28, schrieb Adam D. Ruppe:
 I have what might be a weird request here: a way to get the source code of a
 function (or maybe class, etc. too) out of the compiler as a string literal.

as weird as a _traits( getAST, function ) would be :) my personal feeling is that every compiletime knowledge should be accessable through traits (and maybe change-able)
Oct 15 2010
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:i99vgb$1pju$1 digitalmars.com...
I have what might be a weird request here: a way to get the source code of 
a
 function (or maybe class, etc. too) out of the compiler as a string 
 literal.

 Using existing features, I was able to think up a hacky solution: use
 __FILE__, __LINE__, and string import to get the source and read it in. 
 But my
 implementation was bug riddled, needed extra code at the function, and 
 relied
 on conventions.

 So I'd prefer something built in - a trait addition could do the job. I 
 looked
 at the compiler's source, and it doesn't seem to keep all the needed info
 around, but I imagine it would be a lot easier for it to figure this out 
 than
 doing it with mixins.


 Why would this be useful? My specific case is taking a D function and
 translating it into javascript at run time, so I can print it out to the
 browser and run it there too. (naturally, this requires some conventions 
 and
 simplifcation in the code to work anyway, so my hacky solution works for 
 me).

 Other advantages might be mixing it with string mixins to edit code at 
 compile
 time.


 Honestly, I'm not sure about what else it would be good for. Can anyone 
 think
 of something compelling enough for me to dive into the dmd source and see
 about doing it myself?

 I started typing this excited about the possibilities, but I ended up 
 changing
 my mind while typing the short list of advantages... but let's discuss it. 
 Any
 ideas on how it would be useful?

 Perhaps a simpler alternative would be __traits(sourceFile) and 
 sourceLine -
 to mimic my current solution.

With a __traits(getSource, this_statement), things like assert could display the actual line of code that failed, not just the line number. I'm certainly all for it. I've found myself wishing for it on occasion myself.
Oct 15 2010
prev sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Fri, 15 Oct 2010 12:28:59 -0400, Adam D. Ruppe  
<destructionator gmail.com> wrote:
 I have what might be a weird request here: a way to get the source code  
 of a
 function (or maybe class, etc. too) out of the compiler as a string  
 literal.

 Using existing features, I was able to think up a hacky solution: use
 __FILE__, __LINE__, and string import to get the source and read it in.  
 But my
 implementation was bug riddled, needed extra code at the function, and  
 relied
 on conventions.

 So I'd prefer something built in - a trait addition could do the job. I  
 looked
 at the compiler's source, and it doesn't seem to keep all the needed info
 around, but I imagine it would be a lot easier for it to figure this out  
 than
 doing it with mixins.


 Why would this be useful? My specific case is taking a D function and
 translating it into javascript at run time, so I can print it out to the
 browser and run it there too. (naturally, this requires some conventions  
 and
 simplifcation in the code to work anyway, so my hacky solution works for  
 me).

 Other advantages might be mixing it with string mixins to edit code at  
 compile
 time.


 Honestly, I'm not sure about what else it would be good for. Can anyone  
 think
 of something compelling enough for me to dive into the dmd source and see
 about doing it myself?

 I started typing this excited about the possibilities, but I ended up  
 changing
 my mind while typing the short list of advantages... but let's discuss  
 it. Any
 ideas on how it would be useful?

 Perhaps a simpler alternative would be __traits(sourceFile) and  
 sourceLine -
 to mimic my current solution.

I would favor some form of AST as opposed to raw strings, but I do believe this functionality would be useful. One example from C# is how linq allows backend to generate optimal SQL, etc queries based on the expression tree of the user's lambda functions.
Oct 15 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Robert Jacques" <sandford jhu.edu> wrote in message 
news:op.vknih4dy26stm6 sandford.myhome.westell.com...
 I would favor some form of AST as opposed to raw strings,

Definitely, but strings would probably a lot easier to put in and work well enough in the meantime. I just came across another case where access to original source would be useful. I have a helper tool in my SemiTwistDTools lib that I use all the time that works like this: int a=3; mixin(traceVal!("a+4")); // runtime output: a+4: 7 Which is almost as much a pain to type as it is useful. But if there was a finer-graned version of __traits(getSource, function), say, to get the source of a parameter from the caller's side, then I could probably just simplify it to this: traceVal(a+4); By doing something like this: void traceVal(T, string str = __traits(getParamSource, expr))(T expr) { writeln(str, ": ", expr); } Which would be similar to this trick already in D2: int bar(int line = __LINE__)() { return line; } void main() { #line 1000 writeln(bar()); // Output: 1000 } ...Although in testing that I just noticed that defining bar this way doesn't work the same: template bar(int line = __LINE__) { enum bar = to!string(line); } Bug?
Oct 15 2010
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
Well, it sounds like I'm not the only one who'd find this useful, so I took a
look
at the compiler.

It seems to only store file and line internally (I might have missed something
though) so the path of least resistance seems to be exposing that, and then
pulling the source with a library function.

But I'll keep looking, since avoiding the library function would be nice (no -J
and no bugs!).
Oct 16 2010
parent "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:i9cud5$1um2$1 digitalmars.com...
 Well, it sounds like I'm not the only one who'd find this useful, so I 
 took a look
 at the compiler.

 It seems to only store file and line internally (I might have missed 
 something
 though) so the path of least resistance seems to be exposing that, and 
 then
 pulling the source with a library function.

 But I'll keep looking, since avoiding the library function would be nice 
 (no -J
 and no bugs!).

I've been dealing with ddmd's source a bit lately. Unless it's different in dmd, the entirety of the source file should be available here: // Relevent snippets from ddmd, probably similar in dmd: class Module // in Module.d { File srcfile; } class File // in File.d { ubyte* buffer; // data for our file uint len; // amount of data in buffer[] } So if you have a "Module myModule", then you can get the full original source code of the module with (D-ified): myModule.srcfile.buffer[0..myModule.srcfile.len]; You're right that aside from the Module, dmd only keeps track of filename and line number (via the "Loc" struct, which is a member of most classes in the AST). You should be able to add members to Loc for "starting index in source file" and "ending index", and then just use those to index into Module.srcfile.buffer. (Although at that point, it's not really a "Line Of Code", more like "Location Of Code"...and for all I know there might be places that are reliant on it actually having the semantic meaning of "line of code", expecialy since Loc appears to have an "equals(Loc)" member). I'd probably start by adding those members to Loc's ctors, searching all the files for all Loc instantiations, and updating them as relevent. You'll probably also have to find wherever dmd keeps track of the current line number (probably in the lexer or parser somewere, but I've never looked into those, so I don't even know where they are), and keep track of the current srcIndex, etc. along with it.
Oct 16 2010