February 07, 2007
BCS wrote:
> Walter Bright wrote:
>>
>> No, versions defined in an import do NOT affect the importer.
> 
> What?? then how do you implement non trivial vertion logic?

Do it in a makefile or use constants and static if :-p


Sean
February 07, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> The ability to transform true code trees will come with D's macro abilities. But that's a few months ahead at least.

I can't believe that so many hours have passes since this post and no one has asked for some details?

Is this something you and Walter talked about? (Because it sounds too good to be true.) What will those macros be like?
Examples...?
February 07, 2007
BCS wrote:
> Walter Bright wrote:
>> The function gets inlined.
> 
> The equivalent of this doesn't
> 
> version(RowMajor)
> {
>     x = 0
>     for(i=0;i<max;i++)
>     x+=table[i][j];
> }
> else // RowMinor
> {
>     x = 0
>     for(i=0;i<max;i++)
>     x+=table[j][i];
> }
> and IIRC this doesn't ether
> 
> version(X86) // avoid overflow in midpoint calculations
> {
>     asm
>     {
>         MOV low EAX;
>         ADD EAX hi;
>         RCR EAX 1;
>         MOV EAX mid;
>     }
> }
> else
> {
>     mid = (hi-low)/2 + low;
> }

I agree the inlining isn't perfect. But in the small number of cases where this matters, you can use the version=XXX command line switch.

>>>
>>> ====You can't break across function calls
>>>
>>> switch(i)
>>> {
>>>     case 1:
>>>         version(Baz)
>>>             if(baz) break;
>>>         else
>>>             break;
>>>     case 2:
>>>
>>>     ...// lots of un versioned code
>>> }
>>
>>     if (globalversion.baz && baz)
>>         break;
> 
> The point is to have all of the versioning done by the time you link, that leaves a runtime check for version info.

Not if it's a const.


>>> ====lots of version combinations
>>>
>>> version(Foo) i = foo(i);
>>> version(Boo) i = boo(i);
>>> version(Fig) i = fig(i);
>>> version(Baz) i = baz(i);
>>> version(Bar) i = bar(i);    //32 options???
>>
>>
>> i = abc(i);    // a different abc is implemented for each version.
> 
> All 32 possibilities??? What if there are 16 independent versions? that's 64K functions! And no that is not an unlikely case, say "i" is a parse tree and we want to add different types of annotation depending on what features are enabled.

I'd use bit flags instead of versions for such things. If I had a situation with 32*16 version combinations, I think I'd seriously consider reengineering what the program considers as a "version". After all, do you really want to generate 64,000 binaries? How are you going to test them <g>?
February 07, 2007
Ivan Senji wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> The ability to transform true code trees will come with D's macro abilities. But that's a few months ahead at least.
> 
> I can't believe that so many hours have passes since this post and no one has asked for some details?
> 
> Is this something you and Walter talked about? (Because it sounds too good to be true.) What will those macros be like?
> Examples...?

Nothing at the moment but a lot of:

....
<insert magic here>
voila!

Andrei has been mostly hard at work on the const/inout/scope problem. The current way D does it is hackish, and Andrei feels (and I agree) that bringing rigor to it will make D a considerably stronger language.
February 07, 2007
Yauheni Akhotnikau wrote:
> May be I'm wrong, but I think that 'static if' and recursive templates (and other techniques available for metaprogramming at compile time) are not as powerful as ordinary D itself. So it is much more preferable to me to program such DSL as 'normal' D program. May be it is a good idea to make 'staged' compilation? For example DSL transformation code is written as ordinal D programm. Then that code compiled at first compilation stage, then it is invoked by compiler and the result is placed into input to the next stage.

The main difficulty is if the DSL needs to access symbols in the rest of the D code.
February 07, 2007
BCS a écrit :
> renoX wrote:
>> Pragma a écrit :
>>
>>> BLS wrote:
>>>
>>>> Pragma schrieb:
>>>>
>>>>> BLS wrote:
>>>>
>>>> I can imagine the following scenario : D Compiler is calling a
>>>> Translator, a modified Enki f.i. to translate a Domain Specific Language
>>>> into D ... strange
>>>
>>>
>>> I've thought about that too- much like BCS's work.  The only thing 
>>
>>
>> Enki?
> 
> http://www.dsource.org/projects/ddl/browser/trunk/enki
> written by Pragma
> 
>> BCS?
> 
> http://www.dsource.org/projects/scrapple/browser/trunk/dparser/dparse.d
> written by me (BCS)

Thanks, I was a bit lost.

renoX
> 
>>
>> Could you avoid mysterious references?
>>
>> Regards,
>> renoX
February 07, 2007
Walter Bright wrote:

>> Example of things I am thinking about are "__WXGTK__", "UNICODE",
>> or "HAVE_OPENGL". With C/C++, they're usually in a config.h file.
> 
> I've worked with the C approach for many years, and have gotten increasingly dissatisfied with it. Over time, it leads to conflicting, misused, overlapping version macros.
> 
> I've also tried the "make an API for the version" method, and have been much more satisfied with it. You can see it at work in the gc implementation (see gclinux.d and win32.d).

OK, see what you mean. And the Makefile would pick which
implementation gets used, for the common interface chosen ?

Not sure there's a whole world of difference between the:

version(Win32) // or foowin32.d
void foo() { ...this... }
version(linux) // or foolinux.d
void foo() { ...that... }

and

void foo()
{
version(Win32)
...this...
version(linux)
...that...
}

But any rate, it's preferred to handle it outside of D. OK.
Either through rewriting the code, or in the Makefiles. OK.


With autoconf, I normally want the SAME piece of code to
work on all platforms - so it does a different approach.

For D, I would instead write one piece of code for EACH
platform and avoid versioning it (as much as possible) ?


I've worked with the "./configure && make" approach for
many years and kinda like it, but will try out new ideas.
Then again I kinda like the preprocessor too, and prefer
writing C over C++, so maybe I'm just stuck on the old. :-)

Not changing anything for the "ported" projects (like wxD),
but it will be something to keep in mind for future D ones.
Will do some thinking on how it would apply to options...
(choices, as opposed to just platform/portability macros)

--anders
February 07, 2007
Sean Kelly wrote:
> BCS wrote:
> 
>> Walter Bright wrote:
>>
>>>
>>> No, versions defined in an import do NOT affect the importer.
>>
>>
>> What?? then how do you implement non trivial vertion logic?
> 
> 
> Do it in a makefile or use constants and static if :-p
> 
> 
> Sean

If that is what is needed to make things work, then what is the version statement for?
February 07, 2007
Walter Bright wrote:
> BCS wrote:
> 
>>
>> The point is to have all of the versioning done by the time you link, that leaves a runtime check for version info.
> 
> 
> Not if it's a const.

if it's a const than it should be a static if.

static if(globalversion.baz)
	if(baz) break;
else
	break;

and that still doesn't cover the other case

switch(i)
{
  version(foo)
    case 1:

  ...

  version(!foo)
    case 1:
}

or how about

outer: while(...)
{
 for(...)
 {
  ....... // lots of nesting
        version(Foo)
         break outer;
        else
         continue outer;
 }
}

>> All 32 possibilities??? What if there are 16 independent versions? that's 64K functions! And no that is not an unlikely case, say "i" is a parse tree and we want to add different types of annotation depending on what features are enabled.
> 
> 
> I'd use bit flags instead of versions for such things. 

Runtime checks? That would requirer that code to do the processing be compiled in for all cases: Code bloat, etc. And structures would then need to have all the fields for all the features[*] even if they will never be used: Data bloat etc.

Or are you saying use "static if"? Then what is version for? In that case I can't think of any use AT ALL for version.

Strike that, versions can be specified on the command line so they could do this:

module globalversion;

version(Foo) const bool Foo = true else const bool Foo = false;
....

and then everything is done with static ifs

*version isn't just for controlling code inclusion.

struct Part
{
	version(Foo) Foo foo;
	version(Boo) Boo boo;
	version(Fig) Fig fig;
	version(Baz) Baz baz;
	version(Bar) Bar bar;
}

> If I had a situation with 32*16 version combinations, I think I'd seriously consider reengineering what the program considers as a "version". After all, do you really want to generate 64,000 binaries? How are you going to test them <g>?

Most of the cases where I see version used I would expect to have several orders of magnitude more combinations possible than are ever actually built.

What I would want versioning for would be to be able to arbitrarily select what I want from a set of functionalities. Then by specifying that on the command line, run a build (like with bud or a makefile that doesn't known jack about versions) and get what I want.

I'm at a loss as to what you envision for versioning.
February 07, 2007
On Wed, 07 Feb 2007 11:50:50 -0800, BCS wrote:

>> No, versions defined in an import do NOT affect the importer.
> 
> What?? then how do you implement non trivial vertion logic?
> 
> version(Foo)
> {
> 	// Foo alwys needs Bar
> 	version = Bar
> 
> 	...
> }
> 
> ... more of the like

Not wishing to over promote the Bud tool, but it does implement 'global' version statements.

pragma(export_version):

This allows you to set a global version identifier. DMD allows you to set a version identifier in your code, but the scope of that is only for the module it is set in. This pragma gives you the ability to declare a version identifier which is applied to all modules being compiled, and not just the 'current' module.

Example:
    version(build) pragma(export_version, Unix);
    version(build) pragma(export_version, Limited);
These lines will cause the compiler to have these version identifiers added
to the command line switches, thus making them effectively global. You can
list more than one identifier on the pragma statement ...
    version(build) pragma(export_version, Unix, Limited);

So in your example above ...

  version(build) pragma(export_version, Foo, Bar);

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
8/02/2007 10:19:53 AM