Re: CTFE in betterC needs the GC

2022-10-29 Thread arandomonlooker via Digitalmars-d-learn

On Sunday, 30 October 2022 at 04:14:17 UTC, Ali Çehreli wrote:

On 10/29/22 20:41, arandomonlooker wrote:

> [...]

Although you need that function only at compile time, it is an 
ordinary function that could be called at run time as well. The 
function needs GC for that concatenation in the general case.


[...]


Thank you, Ali.


Re: CTFE in betterC needs the GC

2022-10-29 Thread Ali Çehreli via Digitalmars-d-learn

On 10/29/22 20:41, arandomonlooker wrote:

> string exampleCTFE(string a, string b) {
>  return a ~ b;
> }

Although you need that function only at compile time, it is an ordinary 
function that could be called at run time as well. The function needs GC 
for that concatenation in the general case.


One way of solving your issue would be to change the function to a 
function template and pass the strings as template parameters 
(compile-time parameters):


string exampleCTFE(string a, string b)() {
return a ~ b;
}

which would require explicit function template instantiation:

enum example = exampleCTFE!("A", "BCDE");

which would cause code bloat because exampleCTFE would be instantiated 
for every string combination that was used. For example, the following 
two uses would require two separate instantiations:


enum example1 = exampleCTFE!("A", "BCDE");
enum example2 = exampleCTFE!("A", "BCDEX");

> int main() {

I think you also need to specify main() as extern(C):

extern (C)
int main() {
  // ...
}

Ali



CTFE in betterC needs the GC

2022-10-29 Thread arandomonlooker via Digitalmars-d-learn
Hello, i'm a beginner to the D programming language that has 
posted many times for simple questions and code errors.
I have written a function that manipulates D code (passed through 
a q{...} block) and returns it to be compiled into the program by 
a mixin.
The problem is that i need to do so in -betterC mode, and for 
example, this code does not compile, giving an error that array 
concatenation of two strings at CTFE is not possible without the 
GC:


```d
string exampleCTFE(string a, string b) {
return a ~ b;
}
enum example = exampleCTFE("A", "BCDE");
int main() {
import core.stdc.stdio;
example.puts;
return 0;
}
```

Why it complains about the GC if it's a CTFE expression that is 
built at compile time? There is an alternative that works in 
-betterC mode?

Thanks in advance.



Re: CTFE and BetterC compatibility

2022-04-28 Thread bauss via Digitalmars-d-learn

On Thursday, 28 April 2022 at 12:36:56 UTC, Dennis wrote:

On Thursday, 28 April 2022 at 12:10:44 UTC, bauss wrote:
On Wednesday, 27 April 2022 at 15:40:49 UTC, Adam D Ruppe 
wrote:

but this got killed due to internal D politics. A pity.


A tale as old as time itself


In this case, it was actually a trailing whitespace in the 
changelog entry making the test suite fail, but the PR author 
ceased activity before fixing it and now it has merge conflicts.


https://github.com/dlang/dmd/pull/11014#discussion_r427108067


The fact a trailing white-space has any impact is almost 
laughable.


Re: CTFE and BetterC compatibility

2022-04-28 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 28 April 2022 at 12:36:56 UTC, Dennis wrote:
In this case, it was actually a trailing whitespace in the 
changelog entry making the test suite fail, but the PR author


Stefan's own `assert(__ctfe);` approach was better anyway...


Re: CTFE and BetterC compatibility

2022-04-28 Thread Dennis via Digitalmars-d-learn

On Thursday, 28 April 2022 at 12:10:44 UTC, bauss wrote:

On Wednesday, 27 April 2022 at 15:40:49 UTC, Adam D Ruppe wrote:

but this got killed due to internal D politics. A pity.


A tale as old as time itself


In this case, it was actually a trailing whitespace in the 
changelog entry making the test suite fail, but the PR author 
ceased activity before fixing it and now it has merge conflicts.


https://github.com/dlang/dmd/pull/11014#discussion_r427108067



Re: CTFE and BetterC compatibility

2022-04-28 Thread bauss via Digitalmars-d-learn

On Wednesday, 27 April 2022 at 15:40:49 UTC, Adam D Ruppe wrote:

but this got killed due to internal D politics. A pity.


A tale as old as time itself


Re: CTFE and BetterC compatibility

2022-04-27 Thread Adam D Ruppe via Digitalmars-d-learn

On Wednesday, 27 April 2022 at 14:21:15 UTC, Claude wrote:
The operation requiring the D-runtime is appending the array, 
but it should **only** be done at compile-time.


In that case, you want to prove to the compiler it is only called 
at compile time by encapsulating the function inside a template 
or defining it immediately where it is called.


Delete the stand-alone function `parse` and instead call it like 
this:


```
// define it
enum Data parsedData = function Data (string str) pure
{
Data data;

while (str.length != 0)
{
// Skip spaces
while (str[0] == ' ')
str = str[1 .. $];

// Parse single digit integer
data.digits ~= parseDigit(str[0]);

// Consume digit
str = str[1 .. $];
}

return data;
} ("5 4 2 6 9"); // and call it in the same place
```



Or if you want it to be independently defined still, you can 
define it inside a helper template but you'd have to return a 
basic type instead of Data, so I think calling it immediately is 
what you want to do here.



There was going to be a ctfe-only thing you could put in the 
function so the compiler doesn't try to generate the runtime 
version, but this got killed due to internal D politics. A pity.


Re: CTFE and BetterC compatibility

2022-04-27 Thread Claude via Digitalmars-d-learn
On Wednesday, 27 April 2022 at 14:34:27 UTC, rikki cattermole 
wrote:

This works:


Cool, thanks.

Unfortunately, with that implementation, I need to know the 
maximum size for the array. It works for that particular example, 
but in the context of an XML file analysis, it's a bit awkward.


Regarding my comment above, I tried using cork functions for 
missing symbols: it also works! However the linker does not 
optimize those functions out (I see the symbols in the executable 
binary)...


Re: CTFE and BetterC compatibility

2022-04-27 Thread Claude via Digitalmars-d-learn
On Wednesday, 27 April 2022 at 14:27:43 UTC, Stanislav Blinov 
wrote:
This is a long-standing pain point with BetterC (see 
https://issues.dlang.org/show_bug.cgi?id=19268).


That's what I was afraid of... Thanks for the link to the 
bug-report.


On Wednesday, 27 April 2022 at 14:27:43 UTC, Stanislav Blinov 
wrote:
When not using BetterC, but not linking against druntime 
either, you have to provide your own implementation for those 
functions. This is e.g. so you can replace druntime with your 
own version.


Yeah... The problem is that there will a lot of those functions 
to define (for a whole XML parser). I suppose I can use cork 
functions with empty bodies??


I will check if the linker optimize them out...


Re: CTFE and BetterC compatibility

2022-04-27 Thread rikki cattermole via Digitalmars-d-learn

This works:

```d
struct Data
{
int[] digits;
}

int parseDigit(char c) pure
{
return c - '0';
}

Data parse(string str) pure
{
Data data;

if (__ctfe) {
size_t used;
data.digits.length = str.length;

while (str.length != 0)
{
// Skip spaces
while (str[0] == ' ')
str = str[1 .. $];

// Parse single digit integer
data.digits[used++] = parseDigit(str[0]);

// Consume digit
str = str[1 .. $];
}

data.digits = data.digits[0 .. used];
}

return data;
}

enum Data parsedData = parse("5 4 2 6 9");

extern(C) int main()
{
pragma(msg, "First digit=", parsedData.digits[0]);
return 0;
}
```


Re: CTFE and BetterC compatibility

2022-04-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 27 April 2022 at 14:21:15 UTC, Claude wrote:

This is a long-standing pain point with BetterC (see 
https://issues.dlang.org/show_bug.cgi?id=19268).


As for this:

If I compile without the BetterC switch, compilation actually 
works but I'll have some linker issues:

```
$ gcc test.d -o test
First digit=5
/tmp/ccuPwjdv.o : In function 
« _D5test5parseFNaAyaZS5test4Data » :

test.d:(.text+0x137) : undefined reference to « _d_arraybounds »
test.d:(.text+0x183) : undefined reference to « _d_arraybounds »

etc...
```


When not using BetterC, but not linking against druntime either, 
you have to provide your own implementation for those functions. 
This is e.g. so you can replace druntime with your own version.


Re: CTFE and BetterC compatibility

2022-04-27 Thread Andrea Fontana via Digitalmars-d-learn

On Wednesday, 27 April 2022 at 14:21:15 UTC, Claude wrote:

data.digits ~= parseDigit(str[0]);


Dynamic arrays are not supported using -betterC

Andrea





CTFE and BetterC compatibility

2022-04-27 Thread Claude via Digitalmars-d-learn

Hello,

I want to make a SAX XML parser in D that I could both use at 
run-time or compile-time.


Also when I use it at compile-time, I would like to use BetterC 
so I don't have to link D-runtime.


But I have some compilation problems. I use GDC (GCC 9.4.0).

Here's a reduced sample code:

```
struct Data
{
int[] digits;
}

int parseDigit(char c) pure
{
return c - '0';
}

Data parse(string str) pure
{
Data data;

while (str.length != 0)
{
// Skip spaces
while (str[0] == ' ')
str = str[1 .. $];

// Parse single digit integer
data.digits ~= parseDigit(str[0]);

// Consume digit
str = str[1 .. $];
}

return data;
}

enum Data parsedData = parse("5 4 2 6 9");

extern(C) int main()
{
pragma(msg, "First digit=", parsedData.digits[0]);
return 0;
}
```

If I compile and link against D-runtime, it works:
```
$ gcc test.d -lgdruntime -o test
First digit=5
```

If I compile with BetterC (no D-runtime for GDC), I get a 
compilation error about RTTI:

```
$ gcc test.d -fno-druntime -o test
test.d: In function ‘parse’:
test.d:25:21: error: ‘object.TypeInfo’ cannot be used with 
-fno-rtti

   25 | data.digits ~= parseDigit(str[0]);
  | ^
```

If I compile without the BetterC switch, compilation actually 
works but I'll have some linker issues:

```
$ gcc test.d -o test
First digit=5
/tmp/ccuPwjdv.o : In function 
« _D5test5parseFNaAyaZS5test4Data » :

test.d:(.text+0x137) : undefined reference to « _d_arraybounds »
test.d:(.text+0x183) : undefined reference to « _d_arraybounds »

etc...
```

The operation requiring the D-runtime is appending the array, but 
it should **only** be done at compile-time.


I don't understand why it requires to link against the D-runtime 
whereas it only needs it at compilation-time (and the compilation 
and CTFE interpretation works, as we can see in the last example).


Is there a way to force the compiler to not emit any object ode 
for those functions?


Or am I missing something?

Regards,

Claude


Re: CTFE and -betterC

2018-03-16 Thread Xavier Bigand via Digitalmars-d-learn

Le 16/03/2018 à 22:58, Xavier Bigand a écrit :

Le 15/03/2018 à 01:09, Flamaros a écrit :

On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole wrote:

You will still need DllMain, that is a platform requirement.


I am not sure about that because when DllAnalyser don't see it in the 
opengl32.dll from the system32 directory. And the documentation indicate that 
it is optional.

I finally choose to put the entry points generation in a sub-project that put 
them in a d file, like that it is easier to make the CTFE working and will be 
much better for the debugging and compilation time.

So I have also some few other questions :
 - Is it a bug that ctRegex doesn't with the return of allMembers?
 - What is the status of the new CTFE engine?
 - Will CTFE be able to write files or expose a way to see to resulting 
generated code for a debug purpose?
 - Is there a reason why CTFE is impacted by the -betterC option?




I actually found token strings, but I can't figure out how to cascade them, it 
is even possible?
I tried things like that :

enum loadSystemSymbolsCode = q{
version (Windows)
{
extern (Windows)
void loadSytemSymbols()
{
import core.sys.windows.windows;

immutable string dllFilePath = "C:/Windows/System32/opengl32.dll";

auto hModule = LoadLibraryEx(dllFilePath, null, 0);
if (hModule == null)
{
return;
}
writeln(dllFilePath ~ " loaded.");

"%SYSTEM_BINDINGS%"
}
}
};

enum moduleCode = q{
module api_entry;

import std.stdio : writeln;
import derelict.util.wintypes;

export extern (C)
{
mixin(loadSystemSymbolsCode);
}
};

string getLoadSystemSymbolsCode(string bindinsCode)()
{
return loadSystemSymbolsCode.replace("%SYSTEM_BINDINGS%", bindinsCode);
}

string getModuleCode(string loadSystemSymbolsCode)()
{
return moduleCode.replace("%LOAD_SYSTEM_SYMBOLS%", loadSystemSymbolsCode);
}

voidmain()
{
import std.stdio : File;

auto file = File("../opengl32/src/api_entry.d", "w");

file.writeln(
getModuleCode!(
getLoadSystemSymbolsCode!("test;")())
);
}

Is there some materials for learning to do this kind of things with CTFE?


I feel my self little stupid, I don't need the " in the token string with the 
%WordToReplace%. So I think that the magic will happen.



Re: CTFE and -betterC

2018-03-16 Thread Xavier Bigand via Digitalmars-d-learn

Le 15/03/2018 à 01:09, Flamaros a écrit :

On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole wrote:

You will still need DllMain, that is a platform requirement.


I am not sure about that because when DllAnalyser don't see it in the 
opengl32.dll from the system32 directory. And the documentation indicate that 
it is optional.

I finally choose to put the entry points generation in a sub-project that put 
them in a d file, like that it is easier to make the CTFE working and will be 
much better for the debugging and compilation time.

So I have also some few other questions :
 - Is it a bug that ctRegex doesn't with the return of allMembers?
 - What is the status of the new CTFE engine?
 - Will CTFE be able to write files or expose a way to see to resulting 
generated code for a debug purpose?
 - Is there a reason why CTFE is impacted by the -betterC option?




I actually found token strings, but I can't figure out how to cascade them, it 
is even possible?
I tried things like that :

enum loadSystemSymbolsCode = q{
version (Windows)
{
extern (Windows)
void loadSytemSymbols()
{
import core.sys.windows.windows;

immutable string dllFilePath = "C:/Windows/System32/opengl32.dll";

auto hModule = LoadLibraryEx(dllFilePath, null, 0);
if (hModule == null)
{
return;
}
writeln(dllFilePath ~ " loaded.");

"%SYSTEM_BINDINGS%"
}
}
};

enum moduleCode = q{
module api_entry;

import std.stdio : writeln;
import derelict.util.wintypes;

export extern (C)
{
mixin(loadSystemSymbolsCode);
}
};

string getLoadSystemSymbolsCode(string bindinsCode)()
{
return loadSystemSymbolsCode.replace("%SYSTEM_BINDINGS%", bindinsCode);
}

string getModuleCode(string loadSystemSymbolsCode)()
{
return moduleCode.replace("%LOAD_SYSTEM_SYMBOLS%", loadSystemSymbolsCode);
}

voidmain()
{
import std.stdio : File;

auto file = File("../opengl32/src/api_entry.d", "w");

file.writeln(
getModuleCode!(
getLoadSystemSymbolsCode!("test;")())
);
}

Is there some materials for learning to do this kind of things with CTFE?


Re: CTFE and -betterC

2018-03-14 Thread Flamaros via Digitalmars-d-learn
On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole 
wrote:

You will still need DllMain, that is a platform requirement.


I am not sure about that because when DllAnalyser don't see it in 
the opengl32.dll from the system32 directory. And the 
documentation indicate that it is optional.


I finally choose to put the entry points generation in a 
sub-project that put them in a d file, like that it is easier to 
make the CTFE working and will be much better for the debugging 
and compilation time.


So I have also some few other questions :
 - Is it a bug that ctRegex doesn't with the return of allMembers?
 - What is the status of the new CTFE engine?
 - Will CTFE be able to write files or expose a way to see to 
resulting generated code for a debug purpose?

 - Is there a reason why CTFE is impacted by the -betterC option?



Re: CTFE and -betterC

2018-03-13 Thread rikki cattermole via Digitalmars-d-learn

You will still need DllMain, that is a platform requirement.


CTFE and -betterC

2018-03-13 Thread Xavier Bigand via Digitalmars-d-learn

As I am trying to do a dll that acts exactly like one written in C, I am trying 
to compile my code with the -betterC option. So I would not need the DllMain 
function.

I am not sure that I use the best syntax for my CTFE function to be able to 
make it works with the option -betterC and to maintain it after.

In particular I have following issues (my code is at the end of message) :
 * startsWith function doesn't compile with -betterC
 * can't put static before the first foreach
 * don't really now how to factorize small expressions (oglFunctionName , 
oglFunctionName,...)
 * how to make the code I generate less polluted by conditions and iterations? 
Certainly by naming some previously computed parts with alias?
 * after that how to see the generated result and debug?

Thank you in advance for any help.

module api_entry;

import std.stdio : writeln;
import std.algorithm.searching;

import missing_ogl;

import std.traits;
import std.meta;

static string implementFunctionsOf(string Module, bool removeARB = false)()
{
import std.traits;
import std.regex;
import std.conv;

mixin("import " ~ Module ~ ";");

string  res;

res ~= "extern (C) {\n";

foreach (name; __traits(allMembers, mixin(Module)))
{
static if (name.startsWith("da_")
   && mixin("isCallable!" ~ name))
{
alias derelict_oglFunctionName = Alias!(name[3..$]);
alias oglFunctionName = derelict_oglFunctionName;
alias returnType = Alias!(ReturnType!(mixin(name)).stringof);
alias parametersType = Alias!(Parameters!(mixin(name)).stringof);

static if (removeARB && name.endsWith("ARB"))
oglFunctionName = oglFunctionName[0..$ - 3];

res ~=
"export\n" ~
returnType ~ "\n" ~
oglFunctionName ~
parametersType ~ "\n" ~
"{\n" ~
"writeln(\"" ~ oglFunctionName ~ " is not 
specialized\");\n";

// Forward the call to the driver (with arguments and return the
// value of the forward directly)
res ~= "import " ~ Module ~ ";";

// For a reason I do not understand the compiler can not
// compile with returnType
static if (ReturnType!(mixin(name)).stringof == "int function()")
res ~=
"alias extern (C) " ~ returnType ~ " returnType;\n" ~
"return cast(returnType) ";
else if (returnType != "void")
res ~=
"return ";
res ~=
"" ~ Module ~ "." ~ derelict_oglFunctionName ~ "(";
foreach (i, parameter; Parameters!(mixin(name)))
{
if (i > 0)
res ~= ", ";
// We use the default parameter name variable 
"_param_x" where x
// is the index of the parameter starting from 0
res ~= "_param_" ~ to!string(i);
}
res ~=
");";

res ~=
"}\n";
}
}

res ~=
"}\n";
return res;
}


mixin(implementFunctionsOf!("derelict.opengl3.functions"));
mixin(implementFunctionsOf!("derelict.opengl3.deprecatedFunctions"));