February 17, 2006
"Kyle Furlong" <kylefurlong@gmail.com> wrote in message news:dt3oer$22lg$1@digitaldaemon.com...
> So your dmd compiler emit's references to the _d_whatever extern(C) functions in the runtime, correct?

Yes.

> I'm asking if this is going to be a standard, part of the spec, or vendor specific.

All the stuff in the internal package is meant to be vendor specific. So, yes. For another vendor, the names may change, there may be more or fewer such routines.


February 17, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:dt3phq$23iu$1@digitaldaemon.com...
> I think Kyle is wondering whether a compiler writer could simply sit down and write a D compiler, sans standard library, given the D spec.  I think this is possible insofar as language features are concerned, but it may be less clear regarding any points of contact between the runtime and the GC or standard library code.  For example, internal/gc/gc.d contains a bunch of extern (C) functions (prefixed with "_d_") which probably really belong to the runtime code.  But if this is true, what are the points of contact between the runtime and GC?

For the language implementor, the stuff in std.gc. How operator new interfaces with the gc is up to the language implementor.

> Using Phobos as a guide, one might think a compiler writer must provide a garbage collector as a part of the runtime, while I consider these logically separate libraries.  I think the real goal here is to define a clear separation of labor, so a compiler writer can do his part, a library writer his part, an platform writer his part, and each can be assured that if they follow the spec then their libraries should link against any implementation of the other pieces and work without error.  This is really what I'm making an effort to define, and why I fussed so much over this RegExp business.  Until this last release, things had been distilled to a few well-defined extern (C) functions--no need for imports at all :-)


February 17, 2006
Although syntactically correct, MatchExpression in StaticIfCondition or StaticAssert do not compile. For example:

void main(){static if(!("" ~~ "")){}static assert("" ~~ "");}

Is this intended or an unimplemented feature?


Walter Bright wrote:
> Added match expressions.
> 
> http://www.digitalmars.com/d/changelog.html
> 
> 
> 
February 17, 2006
In article <dt2uj7$1e4l$1@digitaldaemon.com>, Sean Kelly says...
>
>clayasaurus wrote:
>> Derek Parnell wrote:
>>> On Wed, 15 Feb 2006 15:50:03 -0800, Walter Bright wrote:
>>>
>>>
>>>> Also, operating system wildcard thing isn't the one used, it's real regular expressions from std.regexp. So you'd write it as:
>>>>
>>>>     assert(".wav$" ~~ filename);
>>>>
>>>> which means any string ending in ".wav".
>>>
>>> Should that be ...
>>>
>>>        assert("\.wav$" ~~ filename);
>>>
>>> otherwise it would also match things like "somefile.awav" because doesn't the "." in the regexp represents 'any-character'.
>>>
>> 
>> Hrm. The compiler tells me it is an unidentified escape sequence.
>
>Try "\.wav$"r :-)

Or use backticks instead:

assert(`\.wav$` ~~ filename);

- Eric Anderton at yahoo
February 17, 2006
"Wang Zhen" <nehzgnaw@gmail.com> wrote in message news:dt49iv$2hm5$1@digitaldaemon.com...
> Although syntactically correct, MatchExpression in StaticIfCondition or StaticAssert do not compile. For example:
>
> void main(){static if(!("" ~~ "")){}static assert("" ~~ "");}
>
> Is this intended or an unimplemented feature?

The problem is that getting it to work requires the compiler itself to understand regular expressions. Currently, it does not.


February 17, 2006
> The problem is that getting it to work requires the compiler itself to understand regular expressions. Currently, it does not.

You could also perhaps use compile-time templates to evaluate static if regex's.  However, it would be another compiler dependency on a library.

-Craig


February 17, 2006
Walter Bright wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message news:dt3phq$23iu$1@digitaldaemon.com...
>> I think Kyle is wondering whether a compiler writer could simply sit down and write a D compiler, sans standard library, given the D spec.  I think this is possible insofar as language features are concerned, but it may be less clear regarding any points of contact between the runtime and the GC or standard library code.  For example, internal/gc/gc.d contains a bunch of extern (C) functions (prefixed with "_d_") which probably really belong to the runtime code.  But if this is true, what are the points of contact between the runtime and GC?
> 
> For the language implementor, the stuff in std.gc. How operator new interfaces with the gc is up to the language implementor.

But what if the user wants to employ a non-standard GC?  There have already been questions about this for real-time programming and other specialized applications.

While I'm coming to understand your argument about the necessary reliance of runtime code on library code, I do believe that D can only benefit if the scope of this reliance and the means of interaction are well-defined.  You've mentioned that, according to their specs, the C/C++ libraries are inextricably intertwined with the compiler definition, and have said that you consider this something you've sought to fix in D.  And while I don't have the experience with writing C/C++ compilers that you do (and therefore have little exposure to this particular issue), it does seem we somewhat agree on what the correct approach for library design should be.  As a point of discussion, I'd like to outline what I've done with Ares thus far.

First, it's important to note that I consider the runtime to be a distinct library containing anything required for basic language support, the garbage collector similarly separated and devoted to memory management, and the standard library as a third distinct entity which contains all components and interfaces the user is expected to actually interact with.  Phobos already has this basic separation, but the points of interaction between each component aren't particularly well-defined.  For example, if someone wants to provided a specialized garbage collector, what does he do?  A bit of research will reveal that some modules from internal/gc should be removed and a new class of type GC should be created, but this requires more interaction with low-level code than most users want to have.

Second, I believe it's important that the need to import modules across these library boundaries should be avoided if at all possible, as doing so creates a compile-time depencency between them.  Also, it seems logical to assume that the runtime and GC code might not be written in D at all, so the points of interaction should be equally accessible from other languages, implying that all such points of interaction should be extern (C) functions.  This also hass the side-benefit of allowing the functions to be delared in the module they're called, as the name mangling scheme ignores declaration placement.

Since the purpose of a garbage collector is to allocate and manage memory, I see little need to extend its interface beyond this. Therefore I consider the "_d_" prefixed calls in internal/gc/gc.d to really belong to the runtime, where I've moved them.  Currently, a GC library in Ares is required to expose these functions (which are are wrapped in a static class instance for user access in the standard library):

    extern (C) void gc_init();
    extern (C) void gc_term();

    alias void function( void *p, void *dummy ) gc_finalizer;
    extern (C) void gc_setFinalizer( void *p, gc_finalizer fn );

    extern (C) void gc_enable();
    extern (C) void gc_disable();
    extern (C) void gc_collect();

    extern (C) void* gc_malloc( size_t sz );
    extern (C) void* gc_calloc( size_t nm, size_t sz );
    extern (C) void* gc_realloc( void* p, size_t sz );
    extern (C) void gc_free( void* p );

    extern (C) size_t gc_sizeOf( void* p );
    extern (C) size_t gc_capacityOf( void* p );

    extern (C) void gc_addRoot( void* p );
    extern (C) void gc_addRange( void* pbeg, void* pend );

    extern (C) void gc_removeRoot( void* p );
    extern (C) void gc_removeRange( void* pbeg, void* pend );

    extern (C) void gc_pin( void* p );
    extern (C) void gc_unpin( void* p );

I've also considered requiring that the runtime expose an os_getStaticDataSegment function and potentially other OS-specific memory related functions, but haven't gotten around to it so far.

The remaining points of interaction are all provided by the standard library.  First, the callbacks for runtime errors, all of which are expected to throw exceptions as default behavior (though onAssert can be hooked at run-time if the user wishes to signal the debugger or something similar):

    extern (C) void onAssert( char[] file, uint line );
    extern (C) void onOutOfMemory();
    extern (C) void onArrayBoundsError( char[] file, size_t line );
    extern (C) void onSwitchError( char[] file, size_t line );
    extern (C) void onInvalidUtfError( char[] msg, size_t idx );

And then a way to monitor and control multithreading for debugging or GC use:

    extern (C) bit multiThreaded();
    extern (C) void suspendAllThreads();
    extern (C) void resumeAllThreads();
    extern (C) void scanAllThreads( void delegate( void*, void* ) fn );

Also, I suspect I'll now be adding a set of functions for RegExp interaction, but haven't done that yet.

So you can see that, so far, there has been no need to import any modules across library boundaries--all imports are either internal or of C headers (which can be easily declared in the module they're called if desired).  I think Phobos could ultimately benefit from such an arrangement, but it's really not critical at this point.


Sean
February 17, 2006
Walter Bright wrote:
> "Wang Zhen" <nehzgnaw@gmail.com> wrote in message news:dt49iv$2hm5$1@digitaldaemon.com...
> 
>> Although syntactically correct, MatchExpression in
>> StaticIfCondition or StaticAssert do not compile. For example:
>> 
>> void main(){static if(!("" ~~ "")){}static assert("" ~~ "");}
>> 
>> Is this intended or an unimplemented feature?
> 
> The problem is that getting it to work requires the compiler itself
> to understand regular expressions. Currently, it does not.

Intriguing. I'd sure love to hear more about this.

I take it understanding regular expressions is much more than just compiling them? (Like what the runtime does, or Perl, etc.?)
February 18, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:dt5cbc$i49$1@digitaldaemon.com...
> Walter Bright wrote:
>> For the language implementor, the stuff in std.gc. How operator new interfaces with the gc is up to the language implementor.
> But what if the user wants to employ a non-standard GC?  There have already been questions about this for real-time programming and other specialized applications.

I don't know what you mean by non-standard. It must implement the interface in std.gc, and operator new and delete need to work. Other than that, there are a wide range of gc implementation strategies one can use.

> First, it's important to note that I consider the runtime to be a distinct library containing anything required for basic language support, the garbage collector similarly separated and devoted to memory management, and the standard library as a third distinct entity which contains all components and interfaces the user is expected to actually interact with. Phobos already has this basic separation, but the points of interaction between each component aren't particularly well-defined. For example, if someone wants to provided a specialized garbage collector, what does he do?  A bit of research will reveal that some modules from internal/gc should be removed and a new class of type GC should be created, but this requires more interaction with low-level code than most users want to have.

Writing a gc is non-trivial, and someone who is up to that task I doubt will have much difficulty with the interface to it. You're right in that one can't casually create a GC class, but I don't see that as a fault in the interface.

> Second, I believe it's important that the need to import modules across these library boundaries should be avoided if at all possible, as doing so creates a compile-time depencency between them.  Also, it seems logical to assume that the runtime and GC code might not be written in D at all, so the points of interaction should be equally accessible from other languages, implying that all such points of interaction should be extern (C) functions.  This also hass the side-benefit of allowing the functions to be delared in the module they're called, as the name mangling scheme ignores declaration placement.

I don't see the reason why one would want to write a new GC that is not in D. If one wants to use an existing one, say the Boehm GC which is in C, all one needs is a simple wrapper of D functions around the Boehm ones.

> So you can see that, so far, there has been no need to import any modules across library boundaries--all imports are either internal or of C headers (which can be easily declared in the module they're called if desired).  I think Phobos could ultimately benefit from such an arrangement, but it's really not critical at this point.

I see what you're doing, but what is the advantage of avoiding doing the import if you're going to need that code anyway?


February 18, 2006
"Georg Wrede" <georg.wrede@nospam.org> wrote in message news:43F658D2.2000608@nospam.org...
> Walter Bright wrote:
>> "Wang Zhen" <nehzgnaw@gmail.com> wrote in message news:dt49iv$2hm5$1@digitaldaemon.com...
>>
>>> Although syntactically correct, MatchExpression in StaticIfCondition or StaticAssert do not compile. For example:
>>>
>>> void main(){static if(!("" ~~ "")){}static assert("" ~~ "");}
>>>
>>> Is this intended or an unimplemented feature?
>>
>> The problem is that getting it to work requires the compiler itself to understand regular expressions. Currently, it does not.
>
> Intriguing. I'd sure love to hear more about this.

If the compiler is to constant fold regular expressions, then it needs to build in to the compiler exactly what would happen if the regex code was evaluated at runtime.

> I take it understanding regular expressions is much more than just compiling them? (Like what the runtime does, or Perl, etc.?)

I think the confusion here is the difference between compiling a string literal, and compiling the regular expression within the string literal. DMD currently does the former, the latter is done at runtime by std.regexp.