www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - dirEntries within static foreach: memory.d(827): Error: fakePureErrno

reply kdevel <kdevel vogtner.de> writes:
I am trying to get this code compiled:

```TemplateStore.d
module TemplateStore;
import std.path;
import std.conv;
import std.file;

immutable string[string] template_map;

static this ()
{
    static foreach (f; dirEntries (``, `*.html`, 
SpanMode.shallow)) {
       pragma (msg, `reading template <` ~ f ~ ">");
       template_map[f] = import (f);
    }
}
```

dmd v2.082.0 says

...linux/bin64/../../src/druntime/import/core/memory.d(827): 
Error: fakePureErrno cannot be interpreted at compile time, 
because it has no available source code
Error: invalid foreach aggregate <error>
Error: invalid foreach aggregate <error>

If I use an immutable array of file names instead of dirEntries 
the code compiles, but I don't want to update that array each 
time a new template file is added.

As a workaround I wrote a helper which writes the quoted 
filenames comma-separated into a file named `LS` using this 
fragment:

    foreach (f; dirEntries (``, `*.html`, SpanMode.shallow))
       writefln ("`%s`,", f);

Then I try to convince the dmd compiler to read LS and use its 
content as initializer for the immutable array template_files:

    immutable LS = import (`LS`);
    pragma (msg, `LS = <` ~ LS ~ `>`);
    immutable template_files = [
       mixin(LS)
    ];

dmd now says (1) if the list in LS has a trailing comma:

    TemplateStore.d-mixin-13(26): Error: expression expected, not 
End of File

or (2) if the list has no trailing comma:

    TemplateStore.d-mixin-13(13): Error: Using the result of a 
comma expression is not allowed
    TemplateStore.d-mixin-13(14): Error: Using the result of a 
comma expression is not allowed
    TemplateStore.d-mixin-13(15): Error: Using the result of a 
comma expression is not allowed
    :

What can I do about it?
Feb 10 2019
next sibling parent reply Seb <seb wilzba.ch> writes:
On Monday, 11 February 2019 at 00:19:02 UTC, kdevel wrote:
 I am trying to get this code compiled:

 ```TemplateStore.d
 module TemplateStore;
 import std.path;
 import std.conv;
 import std.file;

 [...]
You can't read or list files at compile-time. What are you trying to do?
Feb 10 2019
parent reply kdevel <kdevel vogtner.de> writes:
On Monday, 11 February 2019 at 00:54:27 UTC, Seb wrote:
 On Monday, 11 February 2019 at 00:19:02 UTC, kdevel wrote:
[...]
 You can't read or list files at compile-time.
dmd can read files at compile time using the import function [1]
 What are you trying to do?
Incorporate HTML template files into a CGI binary. After putting [ and ] around the list in LS this works: ```TemplateStore.d module TemplateStore; import std.path; import std.conv; import std.file; immutable string[string] template_map; static this () { immutable LS = import (`LS`); immutable template_files = mixin(LS); static foreach (f; template_files) { pragma (msg, `reading template <` ~ f ~ ">"); template_map[f] = import (f); } } ``` [1] https://forum.dlang.org/thread/njnwacxnvxlwlpjcuyud forum.dlang.org
Feb 10 2019
parent Seb <seb wilzba.ch> writes:
On Monday, 11 February 2019 at 01:05:05 UTC, kdevel wrote:
 On Monday, 11 February 2019 at 00:54:27 UTC, Seb wrote:
 On Monday, 11 February 2019 at 00:19:02 UTC, kdevel wrote:
[...]
 You can't read or list files at compile-time.
dmd can read files at compile time using the import function [1]
Sorry, I should have rephrased: you can't call any OS-level functions at compile-time. This includes std.file.read and std.file.dirEntries.
Feb 10 2019
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, February 10, 2019 5:19:02 PM MST kdevel via Digitalmars-d-learn 
wrote:
 I am trying to get this code compiled:

 ```TemplateStore.d
 module TemplateStore;
 import std.path;
 import std.conv;
 import std.file;

 immutable string[string] template_map;

 static this ()
 {
     static foreach (f; dirEntries (``, `*.html`,
 SpanMode.shallow)) {
        pragma (msg, `reading template <` ~ f ~ ">");
        template_map[f] = import (f);
     }
 }
 ```

 dmd v2.082.0 says

 ...linux/bin64/../../src/druntime/import/core/memory.d(827):
 Error: fakePureErrno cannot be interpreted at compile time,
 because it has no available source code
 Error: invalid foreach aggregate <error>
 Error: invalid foreach aggregate <error>

 If I use an immutable array of file names instead of dirEntries
 the code compiles, but I don't want to update that array each
 time a new template file is added.

 As a workaround I wrote a helper which writes the quoted
 filenames comma-separated into a file named `LS` using this
 fragment:

     foreach (f; dirEntries (``, `*.html`, SpanMode.shallow))
        writefln ("`%s`,", f);

 Then I try to convince the dmd compiler to read LS and use its
 content as initializer for the immutable array template_files:

     immutable LS = import (`LS`);
     pragma (msg, `LS = <` ~ LS ~ `>`);
     immutable template_files = [
        mixin(LS)
     ];

 dmd now says (1) if the list in LS has a trailing comma:

     TemplateStore.d-mixin-13(26): Error: expression expected, not
 End of File

 or (2) if the list has no trailing comma:

     TemplateStore.d-mixin-13(13): Error: Using the result of a
 comma expression is not allowed
     TemplateStore.d-mixin-13(14): Error: Using the result of a
 comma expression is not allowed
     TemplateStore.d-mixin-13(15): Error: Using the result of a
 comma expression is not allowed


 What can I do about it?
Nothing. You can't call C functions during CTFE, because the compiler doesn't have their source code, and all functions that interact with the filesystem have to ultimately call C functions. So, you can't use something like dirEntries with CTFE. The only way that you can do anything along the lines of reading files during CTFE is to use string imports to insert the text of a file directly into the module. - Jonathan M Davis
Feb 10 2019