digitalmars.D - __traits(compiles, ...) returns true for syntactic garbage and for
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "mist" <none none.none> Dec 17 2012
- "monarch_dodra" <monarchdodra gmail.com> Dec 17 2012
- "Simen Kjaeraas" <simen.kjaras gmail.com> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "David Nadlinger" <see klickverbot.at> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
- "Pavel" <proger79 gmail.com> Dec 17 2012
Either I do not understand the work of this feature or it is an
obvious bug:
import std.stdio;
import std.conv;
void main()
{
enum string expr = "DMD compiles this garbage ... iiiii - \"
#### $$$";
enum bool bTest = __traits(compiles, expr);
enum bool bTest2 = __traits(compiles, "int i = q{};");
writeln("bTest: " ~ to!string(bTest));
writeln("bTest2: " ~ to!string(bTest2));
}
Produces (tested with dmd32 2.060 and dmd32 2.059):
bTest: true
bTest2: true
(http://dpaste.dzfl.pl/5d338ab3)
Could you please somebody explain this?
Thanks,
Pavel
Dec 17 2012
Argument is supposed to be not a string but plain D code. And it is pretty logical that string literal is a valid compiling D code, as well as an existing variable name. On Monday, 17 December 2012 at 10:42:38 UTC, Pavel wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
Dec 17 2012
On Monday, 17 December 2012 at 10:42:38 UTC, Pavel wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
__traits(compiles, xxx) just verifies that xxx does not resolve to error. In your case, it resolves to... string! Perhaps you wanted to mixin the string? //---- import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, mixin(expr)); enum bool bTest2 = __traits(compiles, mixin("int i = q{};")); enum bool bTest3 = __traits(compiles, mixin("(int i) => 2*i")); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); writeln("bTest3: " ~ to!string(bTest3)); } //----
Dec 17 2012
On 2012-42-17 11:12, Pavel <proger79 gmail.com> wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
Let's start off with the obligatory 'You're doing it wrong'. __traits(compiles, ...) does not check the content of strings. If you want that, use mixin("somestring"). What your code does is simply check if the string is one that could be embedded in D code, which both of them can. If instead of using strings you do this: enum bool bTest2 = __traits(compiles, {int i = q{};}); You will see that the result is false. -- Simen
Dec 17 2012
On Monday, 17 December 2012 at 10:59:38 UTC, mist wrote:Argument is supposed to be not a string but plain D code. And it is pretty logical that string literal is a valid compiling D code, as well as an existing variable name. On Monday, 17 December 2012 at 10:42:38 UTC, Pavel wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
Thanks for the clarification - now everything is clear!
Dec 17 2012
On Monday, 17 December 2012 at 11:03:01 UTC, Simen Kjaeraas wrote:On 2012-42-17 11:12, Pavel <proger79 gmail.com> wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
Let's start off with the obligatory 'You're doing it wrong'. __traits(compiles, ...) does not check the content of strings. If you want that, use mixin("somestring"). What your code does is simply check if the string is one that could be embedded in D code, which both of them can. If instead of using strings you do this: enum bool bTest2 = __traits(compiles, {int i = q{};}); You will see that the result is false.
Nice hint with __traits(compiles, { <statements> }) - thanks! (Because as I've now read in documentation the __traits(compiles) does not accepts statements directly.) Because when writing templates with operating code as strings it is easy to forget that __traits(compiles, ...) behaves so I suppose it is useful to create a utility template for it: template Compiles(string code) { enum bool Compiles = __traits(compiles, mixin("{" ~ code ~ "}")); } void main() { enum string code1 = "int i = q{};"; enum string code2 = "int i = 5; i++;"; writeln("Compiles `" ~ code1 ~ "`: " ~ to!string(Compiles!code1)); writeln("Compiles `" ~ code2 ~ "`: " ~ to!string(Compiles!code2)); } Pavel
Dec 17 2012
On Monday, 17 December 2012 at 12:04:30 UTC, Pavel wrote:On Monday, 17 December 2012 at 11:03:01 UTC, Simen Kjaeraas wrote:On 2012-42-17 11:12, Pavel <proger79 gmail.com> wrote:Either I do not understand the work of this feature or it is an obvious bug: import std.stdio; import std.conv; void main() { enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$"; enum bool bTest = __traits(compiles, expr); enum bool bTest2 = __traits(compiles, "int i = q{};"); writeln("bTest: " ~ to!string(bTest)); writeln("bTest2: " ~ to!string(bTest2)); } Produces (tested with dmd32 2.060 and dmd32 2.059): bTest: true bTest2: true (http://dpaste.dzfl.pl/5d338ab3) Could you please somebody explain this? Thanks, Pavel
Let's start off with the obligatory 'You're doing it wrong'. __traits(compiles, ...) does not check the content of strings. If you want that, use mixin("somestring"). What your code does is simply check if the string is one that could be embedded in D code, which both of them can. If instead of using strings you do this: enum bool bTest2 = __traits(compiles, {int i = q{};}); You will see that the result is false.
Nice hint with __traits(compiles, { <statements> }) - thanks! (Because as I've now read in documentation the __traits(compiles) does not accepts statements directly.) Because when writing templates with operating code as strings it is easy to forget that __traits(compiles, ...) behaves so I suppose it is useful to create a utility template for it: template Compiles(string code) { enum bool Compiles = __traits(compiles, mixin("{" ~ code ~ "}")); } void main() { enum string code1 = "int i = q{};"; enum string code2 = "int i = 5; i++;"; writeln("Compiles `" ~ code1 ~ "`: " ~ to!string(Compiles!code1)); writeln("Compiles `" ~ code2 ~ "`: " ~ to!string(Compiles!code2)); }
Oops, bad idea - it will work only for self-contained code but will not work when code references some variables from current scope.
Dec 17 2012
On Monday, 17 December 2012 at 12:20:23 UTC, Pavel wrote:Oops, bad idea - it will work only for self-contained code but will not work when code references some variables from current scope.
Template mixin helps to solve the issue, so the utility template can be: mixin template Compiles(string code) { enum bool Result = __traits(compiles, mixin("{" ~ code ~ "}")); } with usage: enum string code1 = "int i = q{};"; int j = 0; enum string code2 = "j++;"; enum string code3 = "void foo(){}"; mixin Compiles!code1 compilesCode1; mixin Compiles!code2 compilesCode2; mixin Compiles!code3 compilesCode3; writeln("Compiles `" ~ code1 ~ "`: " ~ to!string(compilesCode1.Result) ); writeln("Compiles `" ~ code2 ~ "`: " ~ to!string(compilesCode2.Result) ); writeln("Compiles `" ~ code3 ~ "`: " ~ to!string(compilesCode3.Result) ); It seems to me handier to use it from templates manipulating code as strings than usage of __traits(compiles,...) directly. Pavel
Dec 17 2012
On Monday, 17 December 2012 at 14:15:42 UTC, Pavel wrote:It seems to me handier to use it from templates manipulating code as strings than usage of __traits(compiles,...) directly.
I'm not quite sure how this is nicer to use than »enum foo = __traits(compiles, { mixin(bar); });«, but tastes differ… David
Dec 17 2012
On Monday, 17 December 2012 at 14:18:25 UTC, David Nadlinger wrote:On Monday, 17 December 2012 at 14:15:42 UTC, Pavel wrote:It seems to me handier to use it from templates manipulating code as strings than usage of __traits(compiles,...) directly.
I'm not quite sure how this is nicer to use than »enum foo = __traits(compiles, { mixin(bar); });«, but tastes differ…
Yup, it is only IMHO :) Useful for forgetful people as me: because without the utility template it is easy to forget to use 'mixin' and to put the statements in the block.
Dec 17 2012
On Monday, 17 December 2012 at 14:29:49 UTC, Pavel wrote:Yup, it is only IMHO :) Useful for forgetful people as me: because without the utility template it is easy to forget to use 'mixin' and to put the statements in the block.
Corrected template to work with expressions too: mixin template Compiles(string code) { enum bool Result = __traits(compiles, mixin(code)) || __traits(compiles, mixin("{" ~ code ~ "}")); }
Dec 17 2012









"mist" <none none.none> 