www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Permitted locations of a version condition

reply "Phil Deets" <pjdeets2 gmail.com> writes:
Hello, I looked over the language specification, and I could not find any  
statement which says where version conditions are permitted. I assumed  
that they would be permitted most places that #if would be reasonable in  
C, but evidently that is not true as they do not work within enumerations.  
I would definitely like the following code to work.

enum Tag
{
    A, B, C,
    version (5) {
       D, E,
    }
    version (7) {
       F, G,
    }
    // ...
}

Added enumerated values based on versions seems like something that would  
be desirable. I ran into this need when converting a header file to D.

Does anyone know where version conditions are and are not allowed  
currently?
Would version conditions within enumerations be a good feature to add to  
D2?

If people like the idea, but the implementation is prevented due to  
manpower issues, I can possibly try to implement it if you give me a  
pointer on potential issues and where to look within the source code.
Oct 29 2009
next sibling parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Phil Deets wrote:
 Hello, I looked over the language specification, and I could not find
 any statement which says where version conditions are permitted. I
 assumed that they would be permitted most places that #if would be
 reasonable in C, but evidently that is not true as they do not work
 within enumerations. I would definitely like the following code to work.
 
 enum Tag
 {
    A, B, C,
    version (5) {
       D, E,
    }
    version (7) {
       F, G,
    }
    // ...
 }
 
 Added enumerated values based on versions seems like something that
 would be desirable. I ran into this need when converting a header file
 to D.
 
 Does anyone know where version conditions are and are not allowed
 currently?
 Would version conditions within enumerations be a good feature to add to
 D2?
 
 If people like the idea, but the implementation is prevented due to
 manpower issues, I can possibly try to implement it if you give me a
 pointer on potential issues and where to look within the source code.

They be allowed at declaration level and statement level (which is just about everywhere except in enum bodies). If you want to change this, have a look in parse.c, Parser::parseEnum your enum body cc blocks will of course have to only allow enum members in their bodies + more cc blocks, which might be a bit of work, depending on how flexible the relevant structs are. you'll also have to muck around with semantic analysis so it can see the conditionals and expand them correctly. I don't stray outside parse.c much, but I bet enum.c, EnumDeclaration::semantic would be the place to start. And the subject has been brought up before (probably more than once). http://www.digitalmars.com/d/archives/digitalmars/D/Conditional_compilation_inside_asm_and_enum_declarations_93200.html I thought the reason we don't have them is because Walter hates them (read: knows they are evil) and actively seeks to discourage their use. However, she'd be a dandy feature to have, and I wouldn't mind adding her to my local collection of patches (which is almost empty since the last release:) if nothing else.
Oct 29 2009
prev sibling next sibling parent reply "Phil Deets" <pjdeets2 gmail.com> writes:
On Thu, 29 Oct 2009 19:47:50 -0500, Ellery Newcomer  
<ellery-newcomer utulsa.edu> wrote:

 And the subject has been brought up before (probably more than once).

 http://www.digitalmars.com/d/archives/digitalmars/D/Conditional_compilation_inside_asm_and_enum_declarations_93200.html

Oops, didn't mean to repeat past discussion. This didn't show up when I searched for the issue. Thanks for the link and the code tips.
Oct 29 2009
parent BCS <none anon.com> writes:
Hello Phil,

 On Thu, 29 Oct 2009 19:47:50 -0500, Ellery Newcomer
 <ellery-newcomer utulsa.edu> wrote:
 
 And the subject has been brought up before (probably more than once).
 
 http://www.digitalmars.com/d/archives/digitalmars/D/Conditional_compi
 lation_inside_asm_and_enum_declarations_93200.html
 

I searched for the issue. Thanks for the link and the code tips.

If one doesn't already exist, this should be put into the bugzillia: http://d.puremagic.com/issues/
Oct 29 2009
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Phil Deets wrote:
 Hello, I looked over the language specification, and I could not 
 find any statement which says where version conditions are 
 permitted.

Language syntax is generally left to the BNF blocks dotted around the documentation.
 I assumed that they would be permitted most places that #if would 
 be reasonable in C, but evidently that is not true as they do not 
 work within enumerations. 

That's because D's versioning system isn't a preprocessor.
 I would definitely like the following code to work.
 
 enum Tag
 {
    A, B, C,
    version (5) {
       D, E,
    }
    version (7) {
       F, G,
    }
    // ...
 }

So would I, except that it makes more sense to me to have the trailing comma after the '}'. Commas separate, unlike semicolons, which terminate.
 Added enumerated values based on versions seems like something that 
 would be desirable. I ran into this need when converting a header file 
 to D.
 
 Does anyone know where version conditions are and are not allowed 
 currently?

They're allowed wherever the grammar expects either a statement or a declaration.
 Would version conditions within enumerations be a good feature to add to 
 D2?

Yes. Stewart.
Oct 29 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Phil Deets wrote:
 
 I put the comma inside the version block because then there wouldn't be
 duplicate commas if the version was removed. If the version number was 6
 in the above example, it would evaluate to "A, B, C, D, E," with my way,
 but
 
 enum Tag
 {
    A, B, C,
    version (5) {
       D, E
    },
    version (7) {
       F, G
    },
    // ...
 }
 
 would evaluate to "A, B, C, D, E, ," which has two commas in a row.
 However, you could keep version blocks separated with commas if you
 specialized the enum grammar specifically for version blocks, which
 might be the right way to go.

It really doesn't matter. By the time you get around to evaluating the version condition, you'll have thrown away all those commas anyways. All that matters is that you can clearly distinguish the members. However, it will be simpler to implement (and express in ebnf) if you separate versions/members with commas. Like enumBody -> { enumMembers } enumMembers -> enumMember , enumMembers enumMembers -> enumMember , enumMembers -> enumMember enumMember -> Identifier enumMember -> Identifier = AsgExp enumMember -> ccCondition enumBody
Oct 29 2009
prev sibling next sibling parent "Phil Deets" <pjdeets2 gmail.com> writes:
On Thu, 29 Oct 2009 22:16:13 -0500, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 Phil Deets wrote:
 I would definitely like the following code to work.
  enum Tag
 {
    A, B, C,
    version (5) {
       D, E,
    }
    version (7) {
       F, G,
    }
    // ...
 }

So would I, except that it makes more sense to me to have the trailing comma after the '}'. Commas separate, unlike semicolons, which terminate.

I put the comma inside the version block because then there wouldn't be duplicate commas if the version was removed. If the version number was 6 in the above example, it would evaluate to "A, B, C, D, E," with my way, but enum Tag { A, B, C, version (5) { D, E }, version (7) { F, G }, // ... } would evaluate to "A, B, C, D, E, ," which has two commas in a row. However, you could keep version blocks separated with commas if you specialized the enum grammar specifically for version blocks, which might be the right way to go.
Oct 29 2009
prev sibling next sibling parent "Phil Deets" <pjdeets2 gmail.com> writes:
On Thu, 29 Oct 2009 23:26:39 -0500, Ellery Newcomer  
<ellery-newcomer utulsa.edu> wrote:

 Phil Deets wrote:
 I put the comma inside the version block because then there wouldn't be
 duplicate commas if the version was removed. If the version number was 6
 in the above example, it would evaluate to "A, B, C, D, E," with my way,
 but

 enum Tag
 {
    A, B, C,
    version (5) {
       D, E
    },
    version (7) {
       F, G
    },
    // ...
 }

 would evaluate to "A, B, C, D, E, ," which has two commas in a row.
 However, you could keep version blocks separated with commas if you
 specialized the enum grammar specifically for version blocks, which
 might be the right way to go.

It really doesn't matter. By the time you get around to evaluating the version condition, you'll have thrown away all those commas anyways. All that matters is that you can clearly distinguish the members. However, it will be simpler to implement (and express in ebnf) if you separate versions/members with commas. Like enumBody -> { enumMembers } enumMembers -> enumMember , enumMembers enumMembers -> enumMember , enumMembers -> enumMember enumMember -> Identifier enumMember -> Identifier = AsgExp enumMember -> ccCondition enumBody

Good point. That makes sense when I think of it that way. I was thinking in a preprocessor mindset where the text had to make sense if the version just disappeared like the text does with the C preprocessor.
Oct 29 2009
prev sibling parent reply "Phil Deets" <pjdeets2 gmail.com> writes:
On Thu, 29 Oct 2009 19:32:56 -0500, Phil Deets <pjdeets2 gmail.com> wrote:

 enum Tag
 {
     A, B, C,
     version (5) {
        D, E,
     }
     version (7) {
        F, G,
     }
     // ...
 }

Thanks to Daniel Keep on the learn newsgroup, I got a workaround working. template Version(string symbol) { mixin("version("~symbol~") immutable Version = true;"~ " else immutable Version = false;"); } mixin(q"ENUM enum Tag { A, B, ENUM"~(Version!("symbol")?q"ENUM C, D, ENUM":"")~q"ENUM E, } ENUM"); That's not pretty, but it's good enough for me; so I'll probably not do any compiler hacking.
Oct 29 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Phil Deets wrote:
 mixin(q"ENUM
 enum Tag
 {
    A, B,
 ENUM"~(Version!("symbol")?q"ENUM
    C, D,
 ENUM":"")~q"ENUM
    E,
 }
 ENUM");
 
 That's not pretty, but it's good enough for me; so I'll probably not do
 any compiler hacking.

"Not pretty" is putting it very lightly. What's happening in the D community is the same thing that's already happened in the C++ community: - The language is missing some useful features. - The language is also missing an elegant powerful macro system that could be used to add those features. - However, the language has other features that can be abused to provide the functionality in a syntactically ugly way. - D programmers use these language features to write powerful but ugly code. - The language develops a reputation for being overly complex and difficult to read. What makes this case particularly bad is that Walter deliberate chose to limit the power of the 'version' construct in order to prevent overly complex read-only code. -- Rainer Deyke - rainerd eldwood.com
Oct 30 2009
next sibling parent Kagamin <spam here.lot> writes:
Rainer Deyke Wrote:

   - However, the language has other features that can be abused to
 provide the functionality in a syntactically ugly way.
   - D programmers use these language features to write powerful but ugly
 code.

There was a word that macros are not needed because string mixins are more powerful.
Oct 30 2009
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Rainer Deyke wrote:
<snip>
 What makes this case particularly bad is that Walter deliberate chose to
 limit the power of the 'version' construct in order to prevent overly
 complex read-only code.

Actually, AIUI it's just one of many things he did to eliminate the syntactic fragility that C++ has a lot of, thereby making code manipulation tools work better. http://www.digitalmars.com/d/1.0/overview.html "It's time to step back, look at what the preprocessor is used for, and design support for those capabilities directly into the language." Naturally, putting these capabilities into the language has to be done one step at a time. Stewart.
Oct 30 2009