www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - __traits(compiles, ...) returns true for syntactic garbage and for

reply "Pavel" <proger79 gmail.com> writes:
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
next sibling parent "mist" <none none.none> writes:
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
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
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
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
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
prev sibling next sibling parent "Pavel" <proger79 gmail.com> writes:
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
prev sibling next sibling parent "Pavel" <proger79 gmail.com> writes:
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
prev sibling next sibling parent "Pavel" <proger79 gmail.com> writes:
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
prev sibling next sibling parent "Pavel" <proger79 gmail.com> writes:
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
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
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
prev sibling next sibling parent "Pavel" <proger79 gmail.com> writes:
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
prev sibling parent "Pavel" <proger79 gmail.com> writes:
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