www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [Suggestion] Version import

reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Change in 0.101:

"Kris pointed out that version identifiers have global effect, and are 
dependent on which order modules are imported. This is clearly wrong. 
Now, only version and debug definitions on the command line have global 
effect. Others only influence the module they are declared in. 
Furthermore, version and debug definitions can only be done at module 
scope."

With this change, we've lost a capability that the C preprocessor has: 
to use an include file to manipulate version identifiers.

Consider a typical case of version manipulation:
(http://www.digitalmars.com/d/version.html)

     version (ProfessionalEdition)
     {
         version = FeatureA;
         version = FeatureB;
         version = FeatureC;
     }
     version (HomeEdition)
     {
         version = FeatureA;
     }
     ...
     version (FeatureB)
     {
         ... implement Feature B ...
     }

and imagine having to maintain a separate copy of these version 
assignments in each module!

I therefore suggest we allow something like this:

----- versions.d -----
version (ProfessionalEdition) {
     version = FeatureA;
     version = FeatureB;
     version = FeatureC;
}
version (HomeEdition) {
     version = FeatureA;
}
----- somemodule.d -----
version import versions;

version (FeatureB) {
     // ...
}

// ...
----------

The 'version import' declaration would import the version assignments in 
the specified module.  IMO the rules would be:

- version import imports only the version assignments, not the module 
symbol table.

- Version imports in a source file must be declared before regular 
imports and actual module content.

- Where a module has more than one version import, I'm guessing that the 
versions assigned in each would affect those that follow.  This means 
that version imports can depend on each other.

- I'm guessing that version importing would be transitive, but I'm not 
sure if it should be.

- There's no need for a separate 'debug import' declaration - indeed, 
this already means something else.  Rather, version import would import 
debug assignments as well as version assignments.

Stewart.
Oct 19 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 19 Oct 2004 18:32:40 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:
 Change in 0.101:

 "Kris pointed out that version identifiers have global effect, and are 
 dependent on which order modules are imported. This is clearly wrong. 
 Now, only version and debug definitions on the command line have global 
 effect. Others only influence the module they are declared in. 
 Furthermore, version and debug definitions can only be done at module 
 scope."

 With this change, we've lost a capability that the C preprocessor has: 
 to use an include file to manipulate version identifiers.

 Consider a typical case of version manipulation:
 (http://www.digitalmars.com/d/version.html)

      version (ProfessionalEdition)
      {
          version = FeatureA;
          version = FeatureB;
          version = FeatureC;
      }
      version (HomeEdition)
      {
          version = FeatureA;
      }
      ...
      version (FeatureB)
      {
          ... implement Feature B ...
      }

 and imagine having to maintain a separate copy of these version 
 assignments in each module!

 I therefore suggest we allow something like this:

 ----- versions.d -----
 version (ProfessionalEdition) {
      version = FeatureA;
      version = FeatureB;
      version = FeatureC;
 }
 version (HomeEdition) {
      version = FeatureA;
 }
 ----- somemodule.d -----
 version import versions;

 version (FeatureB) {
      // ...
 }

 // ...
 ----------

 The 'version import' declaration would import the version assignments in 
 the specified module.  IMO the rules would be:

 - version import imports only the version assignments, not the module 
 symbol table.

 - Version imports in a source file must be declared before regular 
 imports and actual module content.

 - Where a module has more than one version import, I'm guessing that the 
 versions assigned in each would affect those that follow.  This means 
 that version imports can depend on each other.

 - I'm guessing that version importing would be transitive, but I'm not 
 sure if it should be.

 - There's no need for a separate 'debug import' declaration - indeed, 
 this already means something else.  Rather, version import would import 
 debug assignments as well as version assignments.

I've not run into this problem before (yet) so I may be way off base here, but why not simply allow an optional 'public' or 'private' eg. private version = A; public version = B; version = C; so, when a module imports a module containing the above it see's 'version = B' but not 'version = A' or 'version = C' (as I think version should be private by default) Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 19 2004
parent reply Sjoerd van Leent <svanleent wanadoo.nl> writes:
Regan Heath wrote:
 On Tue, 19 Oct 2004 18:32:40 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
 wrote:
 
 Change in 0.101:

 "Kris pointed out that version identifiers have global effect, and are 
 dependent on which order modules are imported. This is clearly wrong. 
 Now, only version and debug definitions on the command line have 
 global effect. Others only influence the module they are declared in. 
 Furthermore, version and debug definitions can only be done at module 
 scope."

 With this change, we've lost a capability that the C preprocessor has: 
 to use an include file to manipulate version identifiers.

 Consider a typical case of version manipulation:
 (http://www.digitalmars.com/d/version.html)

      version (ProfessionalEdition)
      {
          version = FeatureA;
          version = FeatureB;
          version = FeatureC;
      }
      version (HomeEdition)
      {
          version = FeatureA;
      }
      ...
      version (FeatureB)
      {
          ... implement Feature B ...
      }

 and imagine having to maintain a separate copy of these version 
 assignments in each module!

 I therefore suggest we allow something like this:

 ----- versions.d -----
 version (ProfessionalEdition) {
      version = FeatureA;
      version = FeatureB;
      version = FeatureC;
 }
 version (HomeEdition) {
      version = FeatureA;
 }
 ----- somemodule.d -----
 version import versions;

 version (FeatureB) {
      // ...
 }

 // ...
 ----------

 The 'version import' declaration would import the version assignments 
 in the specified module.  IMO the rules would be:

 - version import imports only the version assignments, not the module 
 symbol table.

 - Version imports in a source file must be declared before regular 
 imports and actual module content.

 - Where a module has more than one version import, I'm guessing that 
 the versions assigned in each would affect those that follow.  This 
 means that version imports can depend on each other.

 - I'm guessing that version importing would be transitive, but I'm not 
 sure if it should be.

 - There's no need for a separate 'debug import' declaration - indeed, 
 this already means something else.  Rather, version import would 
 import debug assignments as well as version assignments.

I've not run into this problem before (yet) so I may be way off base here, but why not simply allow an optional 'public' or 'private' eg. private version = A; public version = B; version = C; so, when a module imports a module containing the above it see's 'version = B' but not 'version = A' or 'version = C' (as I think version should be private by default) Regan.

Wrong. In D every declaration is defaulted to be public. No matter what happens. By the way, why not use version and import alongside? Versions are not meant for other modules. They are for the compiler. If you enter dmd -version A ... you will compile everything in version A but not in version B and C. Regards, Sjoerd
Oct 19 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Tue, 19 Oct 2004 23:10:25 +0200, Sjoerd van Leent 
<svanleent wanadoo.nl> wrote:
 Regan Heath wrote:
 On Tue, 19 Oct 2004 18:32:40 +0100, Stewart Gordon 
 <smjg_1998 yahoo.com> wrote:

 Change in 0.101:

 "Kris pointed out that version identifiers have global effect, and are 
 dependent on which order modules are imported. This is clearly wrong. 
 Now, only version and debug definitions on the command line have 
 global effect. Others only influence the module they are declared in. 
 Furthermore, version and debug definitions can only be done at module 
 scope."

 With this change, we've lost a capability that the C preprocessor has: 
 to use an include file to manipulate version identifiers.

 Consider a typical case of version manipulation:
 (http://www.digitalmars.com/d/version.html)

      version (ProfessionalEdition)
      {
          version = FeatureA;
          version = FeatureB;
          version = FeatureC;
      }
      version (HomeEdition)
      {
          version = FeatureA;
      }
      ...
      version (FeatureB)
      {
          ... implement Feature B ...
      }

 and imagine having to maintain a separate copy of these version 
 assignments in each module!

 I therefore suggest we allow something like this:

 ----- versions.d -----
 version (ProfessionalEdition) {
      version = FeatureA;
      version = FeatureB;
      version = FeatureC;
 }
 version (HomeEdition) {
      version = FeatureA;
 }
 ----- somemodule.d -----
 version import versions;

 version (FeatureB) {
      // ...
 }

 // ...
 ----------

 The 'version import' declaration would import the version assignments 
 in the specified module.  IMO the rules would be:

 - version import imports only the version assignments, not the module 
 symbol table.

 - Version imports in a source file must be declared before regular 
 imports and actual module content.

 - Where a module has more than one version import, I'm guessing that 
 the versions assigned in each would affect those that follow.  This 
 means that version imports can depend on each other.

 - I'm guessing that version importing would be transitive, but I'm not 
 sure if it should be.

 - There's no need for a separate 'debug import' declaration - indeed, 
 this already means something else.  Rather, version import would 
 import debug assignments as well as version assignments.

I've not run into this problem before (yet) so I may be way off base here, but why not simply allow an optional 'public' or 'private' eg. private version = A; public version = B; version = C; so, when a module imports a module containing the above it see's 'version = B' but not 'version = A' or 'version = C' (as I think version should be private by default) Regan.

Wrong. In D every declaration is defaulted to be public.

While that seems to be the pattern, in some cases I think it's a bad thing (TM).
 No matter what happens. By the way, why not use version and import 
 alongside?

I have no idea what you mean :) Example?
 Versions are not meant for other modules. They are for the compiler. If 
 you enter dmd -version A ... you will compile everything in version A 
 but not in version B and C.

While you are correct, I think you have missed the point of this post (either that or I have). The problem is not with version statements supplied on the command line, but with version statements in the code, i.e. --[a.d]-- version = Foo; --[b.d]-- import a; --[c.d]-- import a; The C pre-processor allowed you to specify a version in a file, include that file into other files and share that version information. D doesn't allow this currently. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 19 2004
parent Sjoerd van Leent <svanleent wanadoo.nl> writes:
Regan Heath wrote:

Wrong. In D every declaration is defaulted to be public.

While that seems to be the pattern, in some cases I think it's a bad thing (TM).

I would say, go flaming on Walter, he made that decision, years ago... :)
 
 No matter what happens. By the way, why not use version and import 
 alongside?

I have no idea what you mean :) Example?
 Versions are not meant for other modules. They are for the compiler. 
 If you enter dmd -version A ... you will compile everything in version 
 A but not in version B and C.

While you are correct, I think you have missed the point of this post (either that or I have). The problem is not with version statements supplied on the command line, but with version statements in the code, i.e. --[a.d]-- version = Foo; --[b.d]-- import a; --[c.d]-- import a; The C pre-processor allowed you to specify a version in a file, include that file into other files and share that version information. D doesn't allow this currently. Regan

But it is a question if this is a good thing (or not). Alright I missed out to note that down yesterday. Stil I think it shouldn't get to much muddled with. Currently I am doing dome D work in flex/bison and this is a real pain to implement. Perhaps something like: pragma(setVersion, Foo); would do it nicely... Regards, Sjoerd
Oct 20 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
I understand where you're coming from on this. But hear me out, I'll explain
why D versions are the way they are.

Most C/C++ projects that have been maintained for a few years tend to sink
into an incomprehensible rat's nest of #ifdef's. Each new set of maintainers
tends to leave the old stuff as is and add a new layer of overlapping,
redundant #ifdef identifiers. Sometimes the number of #ifdefs seem to dwarf
the actual code. Trying to figure out which sections of code actually get
compiled can get to be a big problem.

There are also some design principles of D at work here:

1) the contents of a module should not be influenced by whoever imports it,
this is so that the same module will generate the same code no matter who
imports it
2) the order in which imports are given should not affect the meaning
3) parsing needs to be independent of semantics

Above all, I wanted to avoid that morass of #ifdef's and where they came
from.

The solution was to have only two levels of version identifiers - ones local
to a module, and ones global to all the module. The latter are specified on
the command line.

You can achieve the version configuration file approach by putting the
following in a file called, say, version.cmd:

    version=FeatureA
    version=FeatureB
    version=FeatureC

and then add the following to the command line:

    dmd  version.cmd
Oct 19 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Walter wrote:
 I understand where you're coming from on this. But hear me out, I'll explain
 why D versions are the way they are.
 
 Most C/C++ projects that have been maintained for a few years tend to sink
 into an incomprehensible rat's nest of #ifdef's. Each new set of maintainers
 tends to leave the old stuff as is and add a new layer of overlapping,
 redundant #ifdef identifiers. Sometimes the number of #ifdefs seem to dwarf
 the actual code. Trying to figure out which sections of code actually get
 compiled can get to be a big problem.

Having only one or two version imports to traverse, rather than a whole bunch of nested #includes, simplifies this considerably.
 There are also some design principles of D at work here:
 
 1) the contents of a module should not be influenced by whoever imports it,
 this is so that the same module will generate the same code no matter who
 imports it
 2) the order in which imports are given should not affect the meaning

Yes, that's true of the imports we have at the moment. But in my idea, the whole point of version imports is that you specifically want to import something that will influence the module content. Just thinking about it, if you have something like version import qwert; import yuiop; then in the same way as versions assigned in this file don't affect yuiop, neither would the versions assigned in qwert. Hence requiring version imports to be declared before regular imports isn't really necessary.
 3) parsing needs to be independent of semantics

I don't see any way in which my idea would break this. <snip>
 You can achieve the version configuration file approach by putting the
 following in a file called, say, version.cmd:
 
     version=FeatureA
     version=FeatureB
     version=FeatureC
 
 and then add the following to the command line:
 
     dmd  version.cmd

Maybe this'll be adequate. One'll have to see.... Stewart.
Oct 20 2004