www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - New __traits

reply BLM768 <blm768 gmail.com> writes:
For a project I've been working on, I found that it would be 
helpful to have a way to determine whether a symbol represents a 
module or package. Since I couldn't find an easy way to do it, I 
forked DMD and made some tweaks. ;)

Anyway, I uncovered an interesting issue. According to my test 
program (https://gist.github.com/blm768/42f40aa5a0c49bb8bd16), 
these are the "types" of various packages/modules in Phobos:
std:
std.stdio: package, module
std.algorithm: package
std.digest: package

In other words, "std" isn't a package _or_ module, and std.stdio 
is both (even though it's just a single D source file). This 
doesn't seem quite right.

There could be an error in my patch to DMD, but I don't see where 
it could be because it's so simple. The code is at 
https://github.com/blm768/dmd/tree/new_traits if anyone wants to 
look over it.

If anyone can help me figure out what's going on, I'd greatly 
appreciate it.
Nov 24 2015
next sibling parent BLM768 <blm768 gmail.com> writes:
On Wednesday, 25 November 2015 at 01:06:55 UTC, BLM768 wrote:
 In other words, "std" isn't a package _or_ module, and 
 std.stdio is both (even though it's just a single D source 
 file). This doesn't seem quite right.
I just confirmed that this also applies to other root packages, i.e. "core" or any root packages from third-party libraries.
Nov 24 2015
prev sibling parent reply Daniel Murphy <yebbliesnospam gmail.com> writes:
On 25/11/2015 12:06 PM, BLM768 wrote:
 For a project I've been working on, I found that it would be helpful to
 have a way to determine whether a symbol represents a module or package.
 Since I couldn't find an easy way to do it, I forked DMD and made some
 tweaks. ;)

 Anyway, I uncovered an interesting issue. According to my test program
 (https://gist.github.com/blm768/42f40aa5a0c49bb8bd16), these are the
 "types" of various packages/modules in Phobos:
 std:
 std.stdio: package, module
 std.algorithm: package
 std.digest: package

 In other words, "std" isn't a package _or_ module, and std.stdio is both
 (even though it's just a single D source file). This doesn't seem quite
 right.

 There could be an error in my patch to DMD, but I don't see where it
 could be because it's so simple. The code is at
 https://github.com/blm768/dmd/tree/new_traits if anyone wants to look
 over it.

 If anyone can help me figure out what's going on, I'd greatly appreciate
 it.
What you're seeing is just an artifact of how dmd's internals work. 'std' is an 'import' (call Dsymbol.kind() for the category of symbol) and you'll have to resolve it to work out which module/package is being imported. It's possible that this is a bug in the symbol resolution, and that it should have already been resolved to a package. Keep in mind also that isPackage and isModule are RTTI functions, and since Module inherits from Package all modules will appear to be packages if that's all you check.
Nov 25 2015
next sibling parent BLM768 <blm768 gmail.com> writes:
On Wednesday, 25 November 2015 at 15:39:17 UTC, Daniel Murphy 
wrote:
 What you're seeing is just an artifact of how dmd's internals 
 work. 'std' is an 'import' (call Dsymbol.kind() for the 
 category of symbol) and you'll have to resolve it to work out 
 which module/package is being imported.  It's possible that 
 this is a bug in the symbol resolution, and that it should have 
 already been resolved to a package.

 Keep in mind also that isPackage and isModule are RTTI 
 functions, and since Module inherits from Package all modules 
 will appear to be packages if that's all you check.
That helps immensely! I'll play with that a bit. As far as semantics go, if this were ever officially integrated into DMD, would it make sense for __traits(isModule, somePackage) to return false (unless it has a package.d) since the inheritance of Module from Package is basically a DMD implementation detail, or would it be better to just follow DMD's convention directly?
Nov 25 2015
prev sibling parent reply BLM768 <blm768 gmail.com> writes:
On Wednesday, 25 November 2015 at 15:39:17 UTC, Daniel Murphy 
wrote:
 What you're seeing is just an artifact of how dmd's internals 
 work. 'std' is an 'import' (call Dsymbol.kind() for the 
 category of symbol) and you'll have to resolve it to work out 
 which module/package is being imported.  It's possible that 
 this is a bug in the symbol resolution, and that it should have 
 already been resolved to a package.
It seems that I can resolve the import by using "theImport.pkg", but I'm not sure if it's the "correct" way. It works in my tests, though. Is that the right way to do it, or is there a better method?
Nov 25 2015
parent reply Daniel Murphy <yebbliesnospam gmail.com> writes:
On 26/11/2015 9:33 AM, BLM768 wrote:
 On Wednesday, 25 November 2015 at 15:39:17 UTC, Daniel Murphy wrote:
 What you're seeing is just an artifact of how dmd's internals work.
 'std' is an 'import' (call Dsymbol.kind() for the category of symbol)
 and you'll have to resolve it to work out which module/package is
 being imported.  It's possible that this is a bug in the symbol
 resolution, and that it should have already been resolved to a package.
It seems that I can resolve the import by using "theImport.pkg", but I'm not sure if it's the "correct" way. It works in my tests, though. Is that the right way to do it, or is there a better method?
Unfortunately I have no idea. You'll have to have a look at what other code that resolves packages is doing. If you can't find it it might be worth emailing Kenji Hara, since he knows everything.
Nov 25 2015
parent reply BLM768 <blm768 gmail.com> writes:
On Thursday, 26 November 2015 at 02:20:43 UTC, Daniel Murphy 
wrote:
 Unfortunately I have no idea.  You'll have to have a look at 
 what other code that resolves packages is doing.

 If you can't find it it might be worth emailing Kenji Hara, 
 since he knows everything.
Well, expression.d seems to do it this way. It's also got a check for "pkg == null", so maybe I should include that. Currently my code would just swallow the issue and report that the argument isn't a package. Then again, I don't even know whether it's possible for my code to forward-reference an import; if not, pkg will never be null anyway. Maybe I'll just assert it or something...
Nov 26 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, 26 November 2015 at 17:47:00 UTC, BLM768 wrote:
 Then again, I don't even know whether it's possible for my code 
 to forward-reference an import; if not, pkg will never be null 
 anyway. Maybe I'll just assert it or something...
Yes, code can forward-reference an import. e.g. this code compiles just fine: void main() { writeln("Where's my import?"); } import std.stdio; Now, when the import is inside of a function, then it can't be forward-referenced, but that's in line with how variable declarations work. - Jonathan M Davis
Nov 26 2015
parent reply BLM768 <blm768 gmail.com> writes:
On Thursday, 26 November 2015 at 20:56:39 UTC, Jonathan M Davis 
wrote:
 Yes, code can forward-reference an import. e.g. this code 
 compiles just fine:

     void main()
     {
         writeln("Where's my import?");
     }

     import std.stdio;

 Now, when the import is inside of a function, then it can't be 
 forward-referenced, but that's in line with how variable 
 declarations work.

 - Jonathan M Davis
Oh, duh. I should have remembered that. In any case, I my tests work when I forward-reference, too, so I'll probably just put an assert on it and call it good. I've got some unit tests on my code now, so it looks like it's almost time for my first PR. I don't know if this is at all related to how top-level packages aren't resolving to Package objects by the time the __traits run, but while testing this code, I found what seems to be a bug related to __traits(allMembers). Specifically, this code produces an extremely strange output: --- import std.stdio; pragma(msg, __traits(allMembers, std)); void main() {} --- It lists a bunch of symbols that most certainly _aren't_ direct ancestors of the "std" package: "object", "core", "std", "KeepTerminator", "GCC_IO", "HAS_GETDELIM", "FSChar", and a bunch of others. That's a bug, right?
Nov 26 2015
parent BLM768 <blm768 gmail.com> writes:
On Thursday, 26 November 2015 at 23:16:59 UTC, BLM768 wrote:
 [snip]

 It lists a bunch of symbols that most certainly _aren't_ direct 
 ancestors of the "std" package: "object", "core", "std", 
 "KeepTerminator", "GCC_IO", "HAS_GETDELIM", "FSChar", and a 
 bunch of others.

 That's a bug, right?
I've tacked on a comment to the relevant issue (11595) with some info that may or may not help figure out what the problem is. I might play with it, too, but I'm only a junior-level CS student who has basically no familiarity with how DMD does symbol resolution, so I doubt that I'll be able to find exactly where the issue is.
Nov 28 2015