How to create compile-time container?
Andrey Zherikov
andrey.zherikov at gmail.com
Wed Sep 2 09:56:11 UTC 2020
On Tuesday, 1 September 2020 at 19:38:29 UTC, Steven
Schveighoffer wrote:
> On 9/1/20 3:09 PM, Andrey Zherikov wrote:
>> Unfortunately this won't work if there is a function 'bar' in
>> different module that calls 'foo':
>
> You should post a full example you expect to work or not work,
> then we can discuss.
>
> I think it should work (I've tried it), but there are several
> problems that could possibly happen with your code, and it's
> hard to tell what you mean by "won't work" with the incomplete
> code that you posted.
>
> -Steve
Sorry for confusion. I'm trying to implement compile-time
scripting and the idea is pretty simple: I have a script file and
I want to convert it to D code during compilation. I've done some
things but stuck at the point when script includes another script.
For simplicity, let's say that script file has commands (one per
line) with syntax "<command><space><parameter>" and only two
commands available= "msg" to print text and "include" to include
another script.
Here is my code:
==============
void parseFile(string file)()
{
enum script = import(file);
mixin(parseScript(script));
}
string parseScript(string script)
{
string code;
foreach(line; script.lineSplitter())
{
auto idx = line.indexOf(' ');
switch(line[0..idx])
{
case "msg"=
code ~= "writeln(\"" ~ line[idx+1..$] ~ "\");";
break;
case "include"=
code ~= "parseFile!\"" ~ line[idx+1..$] ~ "\";";
break;
default= break;
}
}
return code;
}
void main()
{
parseFile!"script";
}
==============
Everything works well until I have included scripts in
subdirectories:
├── dir1
│ ├── dir2
│ │ └── script
│ └── script
└── script
Content:
============== script
msg hello
include dir1/script
============== dir1/script
msg hello from dir1
include dir2/script
============== dir1/dir2/script
msg hello from dir1/dir2
==============
Compilation fails with "Error: file `"dir2/script"` cannot be
found or not in a path specified with `-J`" (I used simple dmd
-J. -run parser.d) which is expected because parse* functions do
not track the directory where the script is located.
In this simple example the issue can be fixed by passing path to
script as a parameter to parseScript function. But this doesn't
seem to be flexible and extendable solution because there can be
other commands that might call parseFile indirectly (they can
even be in other modules).
Theoretically this can be solved by doing something like this but
it doesn't work because "static variable `paths` cannot be read
at compile time":
==============
string[] paths;
void parseFile(string file)()
{
enum path = paths.length > 0 ? buildPath(paths[$-1],
file.dirName()) : file.dirName();
paths ~= path;
scope(exit) paths = paths[0..$-1];
enum script = import(buildPath(path, file));
mixin(parseScript(script));
}
==============
Note that the whole point is to do this parsing at compile time.
More information about the Digitalmars-d-learn
mailing list