www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to get all modules in a package at CT?

reply Domain <dont_email empty.com> writes:
I have a package named command, and many modules inside it, such 
as command.build, command.pack, command.help...
I want to get all these modules at compile time so that I know 
what command is available.
Nov 24 2018
next sibling parent reply Anonymouse <asdf asdf.net> writes:
On Saturday, 24 November 2018 at 08:44:19 UTC, Domain wrote:
 I have a package named command, and many modules inside it, 
 such as command.build, command.pack, command.help...
 I want to get all these modules at compile time so that I know 
 what command is available.
If you just want static if expressions of whether *known* modules are available or not, then test if __traits(identifier, package.module) compiles. --- // Two-step workaround for https://issues.dlang.org/show_bug.cgi?id=19409 enum hasBuild = __traits(compiles, __traits(identifier, command.build)); enum hasPack = __traits(compiles, __traits(identifier, command.pack)); enum hasHelp = __traits(compiles, __traits(identifier, command.help)); static if (hasBuild) { /* ... */ } static if (hasPack) { /* ... */ } static if (hasHelp) { /* ... */ } --- __traits(compiles, { import package.module; }) mostly works, but I ran into problems when the module was available and merely did not compile. If you want to iterate the package for modules imported in it, I'm not sure. __traits(allMembers, package) will list names of imported packages but not which modules.
Nov 24 2018
parent reply mw <m g.c> writes:
On Saturday, 24 November 2018 at 15:21:57 UTC, Anonymouse wrote:
 On Saturday, 24 November 2018 at 08:44:19 UTC, Domain wrote:
 I have a package named command, and many modules inside it, 
 such as command.build, command.pack, command.help...
 I want to get all these modules at compile time so that I know 
 what command is available.
If you just want static if expressions of whether *known* modules are available or not, then test if __traits(identifier, package.module) compiles. --- // Two-step workaround for https://issues.dlang.org/show_bug.cgi?id=19409 enum hasBuild = __traits(compiles, __traits(identifier, command.build)); enum hasPack = __traits(compiles, __traits(identifier, command.pack)); enum hasHelp = __traits(compiles, __traits(identifier, command.help)); static if (hasBuild) { /* ... */ } static if (hasPack) { /* ... */ } static if (hasHelp) { /* ... */ } --- __traits(compiles, { import package.module; }) mostly works, but I ran into problems when the module was available and merely did not compile. If you want to iterate the package for modules imported in it, I'm not sure. __traits(allMembers, package) will list names of imported packages but not which modules.
How to list unknown sub-modules? (and not walking the source tree dir). Is there a compile time solution to this problem? Thanks.
Oct 05 2023
parent reply user1234 <user1234 12.de> writes:
On Thursday, 5 October 2023 at 18:40:36 UTC, mw wrote:
 On Saturday, 24 November 2018 at 15:21:57 UTC, Anonymouse wrote:
 On Saturday, 24 November 2018 at 08:44:19 UTC, Domain wrote:
 I have a package named command, and many modules inside it, 
 such as command.build, command.pack, command.help...
 I want to get all these modules at compile time so that I 
 know what command is available.
If you just want static if expressions of whether *known* modules are available or not, then test if __traits(identifier, package.module) compiles. --- // Two-step workaround for https://issues.dlang.org/show_bug.cgi?id=19409 enum hasBuild = __traits(compiles, __traits(identifier, command.build)); enum hasPack = __traits(compiles, __traits(identifier, command.pack)); enum hasHelp = __traits(compiles, __traits(identifier, command.help)); static if (hasBuild) { /* ... */ } static if (hasPack) { /* ... */ } static if (hasHelp) { /* ... */ } --- __traits(compiles, { import package.module; }) mostly works, but I ran into problems when the module was available and merely did not compile. If you want to iterate the package for modules imported in it, I'm not sure. __traits(allMembers, package) will list names of imported packages but not which modules.
How to list unknown sub-modules? (and not walking the source tree dir). Is there a compile time solution to this problem? Thanks.
No. Sorry. Generally compile time code cannot interact with the system. To be evaluable at compile time code has to be strongly pure, that is not the case of the function you would need. Otherwise you'd need a new traits for that... but that traits would violate the rule explained before.
 If you want to iterate the package for modules imported in it, 
 I'm not sure. __traits(allMembers, package) will list names of 
 imported packages but not which modules.
static reflection on import decls is broken, that wont work well
Oct 05 2023
parent reply mw <m g.c> writes:
On Thursday, 5 October 2023 at 20:07:38 UTC, user1234 wrote:
 No. Sorry.

 Generally compile time code cannot interact with the system. To 
 be evaluable at compile time code has to be strongly pure, that 
 is not the case of the function you would need.

 Otherwise you'd need a new traits for that... but that traits 
 would violate the rule explained before.

 If you want to iterate the package for modules imported in 
 it, I'm not sure. __traits(allMembers, package) will list 
 names of imported packages but not which modules.
static reflection on import decls is broken, that wont work well
So how about at runtime? I just want the compiler to help to list them, instead of doing manually.
Oct 05 2023
next sibling parent user1234 <user1234 12.de> writes:
On Thursday, 5 October 2023 at 20:42:26 UTC, mw wrote:
 On Thursday, 5 October 2023 at 20:07:38 UTC, user1234 wrote:
 No. Sorry.

 Generally compile time code cannot interact with the system. 
 To be evaluable at compile time code has to be strongly pure, 
 that is not the case of the function you would need.

 Otherwise you'd need a new traits for that... but that traits 
 would violate the rule explained before.

 If you want to iterate the package for modules imported in 
 it, I'm not sure. __traits(allMembers, package) will list 
 names of imported packages but not which modules.
static reflection on import decls is broken, that wont work well
So how about at runtime? I just want the compiler to help to list them, instead of doing manually.
I dont have in mind what info are provided by TypeInfoModule but maybe.
Oct 05 2023
prev sibling parent reply cc <cc nevernet.com> writes:
On Thursday, 5 October 2023 at 20:42:26 UTC, mw wrote:
 On Thursday, 5 October 2023 at 20:07:38 UTC, user1234 wrote:
 No. Sorry.

 Generally compile time code cannot interact with the system. 
 To be evaluable at compile time code has to be strongly pure, 
 that is not the case of the function you would need.

 Otherwise you'd need a new traits for that... but that traits 
 would violate the rule explained before.

 If you want to iterate the package for modules imported in 
 it, I'm not sure. __traits(allMembers, package) will list 
 names of imported packages but not which modules.
static reflection on import decls is broken, that wont work well
So how about at runtime? I just want the compiler to help to list them, instead of doing manually.
At runtime, simply: ```d foreach (m; ModuleInfo) { writeln(m.name); } ``` However, Walter has hinted that he wants to remove ModuleInfo at some point.
Oct 05 2023
parent reply mw <mw g.c> writes:
On Thursday, 5 October 2023 at 21:25:54 UTC, cc wrote:
 So how about at runtime? I just want the compiler to help to 
 list them, instead of doing manually.
At runtime, simply: ```d foreach (m; ModuleInfo) { writeln(m.name); } ``` However, Walter has hinted that he wants to remove ModuleInfo at some point.
So ModuleInfo contains all the modules (transitive closure) built into the current binary that is running? Is there document about this ModuleInfo? I only find Struct object.ModuleInfo https://dlang.org/library/object/module_info.html Which seems different.
Oct 05 2023
parent evilrat <evilrat666 gmail.com> writes:
On Thursday, 5 October 2023 at 22:32:36 UTC, mw wrote:
 So ModuleInfo contains all the modules (transitive closure) 
 built into the current binary that is running?

 Is there document about this ModuleInfo?

 I only find Struct object.ModuleInfo

 https://dlang.org/library/object/module_info.html

 Which seems different.
It is opApply() overload on that struct that works with foreach or custom delegate. Since it calls internal stuff there is no point messing up with that. https://github.com/dlang/dmd/blob/d06917a8327027f94b0be0b8e54e47a51ba34134/druntime/src/object.d#L2441
Oct 05 2023
prev sibling next sibling parent Neia Neutuladh <neia ikeran.org> writes:
Easiest way is to put this in your build script:

find path/to/package -name '*.d' | \
   xargs grep '^module ' | \
   sed 's,^module,import,' \
   > data/modules.d

Add `-J data` to your DMD command line, or add `"stringImportPaths":
["data"]` to dub.json.

Then in your file:

mixin(import("modules.d"));
Nov 24 2018
prev sibling parent Andre Pany <andre s-e-a-p.de> writes:
On Saturday, 24 November 2018 at 08:44:19 UTC, Domain wrote:
 I have a package named command, and many modules inside it, 
 such as command.build, command.pack, command.help...
 I want to get all these modules at compile time so that I know 
 what command is available.
As far as I understand there is s.th. called separate compilations. Your program may is compiled in parts. Your logic which loops over the modules only knows which modules are available at the specific point in time. I do not know whether there is some functionality which tells you all modules available at compile time. But if this functionality exists, you (the developer) has to be aware of separate compilation and should have a plan how to mitigate. Either do not use separate compilation or always force recompilation of all source code files... In would really like to have such functionality and also the possibility to express in code: always recompile this part of code (the loop over the modules) even in separate compilation. I do not know whether that is technically possible... Kind regards Andre
Nov 25 2018