www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Source expression passed to a lazy parameter

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Is it possible to get the source expression sent to a lazy 
function?

So that I can implement something like

show(Arg)(lazy Arg arg)
{
     writeln(arg.sourceof, arg);
}

used as

     show(1+2+3);

will print

     1+2+3:6
Apr 09 2018
next sibling parent Basile B. <b2.temp gmx.com> writes:
On Monday, 9 April 2018 at 08:27:50 UTC, Per Nordlöw wrote:
 Is it possible to get the source expression sent to a lazy 
 function?

 So that I can implement something like

 show(Arg)(lazy Arg arg)
 {
     writeln(arg.sourceof, arg);
 }

 used as

     show(1+2+3);

 will print

     1+2+3:6
No (afaik), what you need is an internal compiler function, "toChars" IIRC, that's available for each node.
Apr 09 2018
prev sibling next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Monday, April 09, 2018 08:27:50 Per Nordlöw via Digitalmars-d-learn 
wrote:
 Is it possible to get the source expression sent to a lazy
 function?

 So that I can implement something like

 show(Arg)(lazy Arg arg)
 {
      writeln(arg.sourceof, arg);
 }

 used as

      show(1+2+3);

 will print

      1+2+3:6
Given how lazy parameters work, I don't see how that would be possible. lazy parameters are implemented as delegates, and the function doesn't have access to what the argument was, just the delegate to get the result of evaluating it. Functions with lazy parameters don't have to be templates, and if the function is a template, as long as the type of the expression is the same, it should only result in one instantiation of the function template. As such, the only way that something like what you're suggesting would work would be if there were some way to get the string representation of the body of a delegate at runtime, and that would be pretty much the same as getting the string representation of any function at runtime. That sort of thing simply isn't kept around beyond what's required to compile the function in the first place. The closest that you'd get would be whatever comes with debug symbols when they're enabled. - Jonathan M Davis
Apr 09 2018
prev sibling next sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 9 April 2018 at 08:27:50 UTC, Per Nordlöw wrote:
 Is it possible to get the source expression sent to a lazy 
 function?
Nope. Something along the lines of __traits(getSource, arg) has been discussed occasionally. For lazy what you're asking is impossible, since the compiler doesn't know which actual arguments have been passed. show(1+2) will look absolutely identical to show(3), will look identical to show(myVarWithValue3). Now, there are some things you can do. Notably, lambdas are included verbatim in templated type names, which we can exploit. struct S(alias fn) {} void show(alias fn)() { import std.stdio; writeln(S!fn.stringof[18..$-1], ": ", fn()); } unittest { show!(()=>1+2); // prints "3: 3" } As we can see, it optimizes '1+2' to become 3, so it's not perfect. This also works for lambdas that include local variables: unittest { int i = 13; show!(() => i+2); // Prints "i + 2: 15" } However, it fails for lambdas that take arguments: struct S(alias fn) {} void show(alias fn, T...)(T args) { import std.stdio; writeln(S!fn.stringof[18..$-1], ": ", fn(args)); } unittest { show!(a => a+2)(3); // Fails to compile } The reason this fails is the lambda's textual representation decays to '__lambda1'. There is however still something we can do, but things get even less flexible: struct show(alias fn) { static void opCall(T...)(T args) { import std.stdio, std.string; enum s = show.stringof; enum i = s.indexOf("=>"); writeln(s[i+3..$-1], ": ", fn(args)); } } unittest { show!(a => a+2)(3); // Prints "a + 2: 5" } -- Simen
Apr 09 2018
parent reply Alex <sascha.orlov gmail.com> writes:
On Monday, 9 April 2018 at 09:20:42 UTC, Simen Kjærås wrote:
 Nope. Something along the lines of __traits(getSource, arg) has 
 been discussed occasionally.
Is this available somehow? And/or do you have a link to the discussion, maybe?
Apr 09 2018
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 9 April 2018 at 11:33:56 UTC, Alex wrote:
 On Monday, 9 April 2018 at 09:20:42 UTC, Simen Kjærås wrote:
 Nope. Something along the lines of __traits(getSource, arg) 
 has been discussed occasionally.
Is this available somehow? And/or do you have a link to the discussion, maybe?
https://forum.dlang.org/post/huyqfcoosgzfneswnrur forum.dlang.org https://github.com/dlang/dmd/pull/953 I'm pretty sure there have been other discussions too, but a brief search yielded too many irrelevant results. -- Simen
Apr 09 2018
parent Seb <seb wilzba.ch> writes:
On Monday, 9 April 2018 at 13:03:38 UTC, Simen Kjærås wrote:
 On Monday, 9 April 2018 at 11:33:56 UTC, Alex wrote:
 On Monday, 9 April 2018 at 09:20:42 UTC, Simen Kjærås wrote:
 Nope. Something along the lines of __traits(getSource, arg) 
 has been discussed occasionally.
Is this available somehow? And/or do you have a link to the discussion, maybe?
https://forum.dlang.org/post/huyqfcoosgzfneswnrur forum.dlang.org https://github.com/dlang/dmd/pull/953 I'm pretty sure there have been other discussions too, but a brief search yielded too many irrelevant results. -- Simen
For reference, the most recent discussion and PR is https://github.com/dlang/dmd/pull/7821 (it's currently orphaned)
Apr 09 2018
prev sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 9 April 2018 at 08:27:50 UTC, Per Nordlöw wrote:
 Is it possible to get the source expression sent to a lazy 
 function?

 So that I can implement something like

 show(Arg)(lazy Arg arg)
 {
     writeln(arg.sourceof, arg);
 }

 used as

     show(1+2+3);

 will print

     1+2+3:6
Because of the way D works with a given piece of code may not have a source-location or even a representation which is valid D source code. Note: There is a way to fix this but it's very involved. Step 1: you use cow (copy-on-write) when modifying AST nodes in semantic() or you keep distinct trees. Step 2: you sanitize implicitly generated code to make sure it's actually valid code. Step 3: you write the generated code, to a well-defined location such that source-of can point to a valid location. also note that support for sourceof at compiletime will bloat the executable since it needs to store the source-text.
Apr 09 2018