July 31, 2018
On Tuesday, 31 July 2018 at 06:12:40 UTC, Walter Bright wrote:
>
> Thirdly, C and C++ are loaded to the gills with seemed-like-a-good-idea-at-the-time solutions that turned out to have bad unintended consequences that bork up the language for everyone down the line. D has some of those, too.

And only experience can tell if those ideas turn out to be bad, as people make use of it and realize how (im)practical they are.

We only got a handful known serious users of `extern (C++)` on Windows, and probably only me on POSIX (because anything templated doesn't mangle properly on POSIX, so the STL is unusable).

So if all users come together to say that the current design seemed-like-a-good-idea-at-the-time (to you) but is not, and could be *simplified* to yield a better product, it sounds very backward to not listen to them.
July 31, 2018
On Monday, 30 July 2018 at 19:51:09 UTC, Walter Bright wrote:
> On 7/30/2018 6:45 AM, Atila Neves wrote:
>> On Friday, 27 July 2018 at 22:50:20 UTC, Walter Bright wrote:
>>> On 7/27/2018 10:28 AM, Atila Neves wrote:
>>>> But all I'm trying to do here is tell the D compiler how to mangle symbols.
>>>
>>> Namespaces have semantic implications, too, such as overload resolutions. A namespace introduces a new scope, not just a mangling.
>> 
>> Should they, though?
>
> They do in C++. That was the whole point of adding namespaces:
>
> C:    void ns_foo();
> C++:  namespace ns { void foo(); }

I meant "should they in D, though?". I don't want to import C++ semantics into D. I want D to correctly mangle C++ namespaced functions and change nothing at all about overload resolution in D.

>> Structs aren't namespaces, I wouldn't expect them to behave the same.
>
> From a language perspective, they are namespaces.

Technically, yes. But not C++ namespaces.

> C++ has a lot of bizarre name lookup behavior.

It does. I don't think anyone is suggesting we copy it.

>> I didn't know about this and it makes things better, but it's not a real solution to my problem.
>
> See my other post doing this same thing with structs.

It's not the same - if I want to link to std::vector and std::string, I'd expect them to be used in D as std.vector and std.string, not std.vector and HackyDThing0.std.string.


>> I'm arguing that reopening should be allowed.
>
> As detailed in another post, this opens a whole host of other problems. Even in C++, what names are visible in a namespace at any particular point in the compilation is a nebulous concept. (It is actually carefully specified, but you have to be a language lawyer / compiler implementer to know what they are - to the user it is erratic, random, and nebulous.)

Right, but D doesn't have to do any of that - as far as D is concerned it's just mangling. Well, as far as the typical D user that writes `extern(C++)` anyway.


July 31, 2018
On Monday, 30 July 2018 at 20:23:25 UTC, Walter Bright wrote:
> On 7/30/2018 9:45 AM, Manu wrote:
>> Sure it 'works', but it's an annoying point of friction, and it
>> doesn't need to be that way.
>
> You can reduce it to:
>
>     mixin(cppNamespace("ns", "void foo();"));
>
>
>>> You haven't explained why you can't just move the namespace ns declarations in
>>> one file together.
>> 
>> Are you serious?
>
> Yes, please explain why you can't coalesce the namespace declarations in one C++ file into one namespace declaration.

Because one C++ file != one C++ translation unit. All of them will #include other files and need the symbols in them, which, for anything using namespaces (the standard library, boost, ...), will mean several instances of opening and closing the same namespace.

The only good way (I don't think the mixin template and struct solutions count) to link to any of that today would be to have one enormous D file with _everything_ in it, including nested namespaces.
July 31, 2018
On Tuesday, 31 July 2018 at 08:33:52 UTC, Daniel N wrote:
> On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote:
>> On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote:
>>> On 7/28/2018 11:18 AM, Manu wrote:
>>>> Make a PR that implements namespace as a string... I will use that fork of D forever.
>>>
>>> 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.)
>>>
>>> 2. Use:
>>>
>>>    pragma(mangle, "the mangled name")
>>
>> This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is.
>
> What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now.
>
> template fun()
> {
>     pragma(mangle, "_ZN2ns3funEv")
>     extern(C++)
>     void fun() {}
> }
>
> mixin fun;

Your template doesn't have any template parameter. Bear in mind mangling is dependent on the instance, not the declaration.

Once you add some template parameter, you need to mangle your template parameter list, which you could *almost* reasonably do with CTFE, but since you are on POSIX, you also got fun things like components and template parameter substitution.

Example:
```
    struct Array16479 (Arg) { Arg* data; }
    Array16479!(FuncT2) func16479_4 (FuncT1, FuncT2) (FuncT1);
    static assert(func16479_4!(int, float).mangleof
                  == `_Z11func16479_4IifE10Array16479IT0_ET_`);
```
As you see the return value (`Array16479IT0_E`) encode a backreference to the symbol's template parameter: T0_ reference the second template argument.
If you throw some more language features (e.g. aliases) you quickly realize you need a full semantic analysis to get the mangling right on templates.

More test cases/examples (and shameless self plug): https://github.com/dlang/dmd/pull/8455/files
July 31, 2018
On Tuesday, 31 July 2018 at 08:33:52 UTC, Daniel N wrote:
> On Monday, 30 July 2018 at 13:48:46 UTC, Atila Neves wrote:
>> On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote:
>>> On 7/28/2018 11:18 AM, Manu wrote:
>>>> Make a PR that implements namespace as a string... I will use that fork of D forever.
>>>
>>> 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.)
>>>
>>> 2. Use:
>>>
>>>    pragma(mangle, "the mangled name")
>>
>> This doesn't work for templates. If it did I wouldn't have an issue since libclang tells me what the mangling is.
>
> What is the deal-breaker with templates? For simple functions libclang + pragma seems the best option right now.
>
> template fun()
> {
>     pragma(mangle, "_ZN2ns3funEv")
>     extern(C++)
>     void fun() {}
> }
>
> mixin fun;

extern(C++) {
    void foo(T)() {
    }
}

It doesn't have a mangling until it has an instantiation. Even if it were possible to know which exact instantitations the code that imports this uses, there's no way I can declare the mangling scheme to the D compiler.
July 31, 2018
On 2018-07-31 10:12, Manu wrote:

> Given your favourite example:
> ----
> module a;
> extern(C++, ns) void foo();
> ----
> module b;
> extern(C++, ns) void foo();
> -----
> module c;
> import a, b;
> foo(); // error: ambiguous
> ns.foo(); // error, ambiguous (obviously)
> a.ns.foo(); // naturally, this works... it's the D module that
> correctly organises the symbol. 'ns' is worthless here

This works:

a.foo();

You don't need "ns" in between the module name and the function.

-- 
/Jacob Carlborg
July 31, 2018
On Tue., 31 Jul. 2018, 3:40 am Jacob Carlborg via Digitalmars-d, < digitalmars-d@puremagic.com> wrote:

> On 2018-07-31 10:12, Manu wrote:
>
> > Given your favourite example:
> > ----
> > module a;
> > extern(C++, ns) void foo();
> > ----
> > module b;
> > extern(C++, ns) void foo();
> > -----
> > module c;
> > import a, b;
> > foo(); // error: ambiguous
> > ns.foo(); // error, ambiguous (obviously)
> > a.ns.foo(); // naturally, this works... it's the D module that
> > correctly organises the symbol. 'ns' is worthless here
>
> This works:
>
> a.foo();
>
> You don't need "ns" in between the module name and the function.
>

Right... But did you miss the point? The D module does the organisation (as
you show). The ns offers nothing and creates other kinds of problems.
Just because name resolution traverses the namespace (in simple cases),
there is an entire language of complexity that interacts with that name
lookup, and as far as I know, it has never proven useful, but rather, only
complicated and annoying leading to boilerplate and hacks in certain
situations. (ie, this thread exists and many others)


July 31, 2018
On Saturday, 28 July 2018 at 01:03:10 UTC, Walter Bright wrote:
> On 7/27/2018 4:15 PM, Laeeth Isharc wrote:
>> Can you think of a pragmatic solution to Atila's problem?
>
> One way is for the C++ => D translator to gather all the members of a namespace before trying to emit them. Since D does not impose an order on declarations (unlike C++) it is not constrained to follow the same order.

So a new post preprocessor stage that parses the produced D code and regroups to group the declarations in the same namespace together ?  Using DMD as a library or libdparse or something?



July 31, 2018
On Tuesday, 31 July 2018 at 16:23:55 UTC, Manu wrote:
> On Tue., 31 Jul. 2018, 3:40 am Jacob Carlborg via Digitalmars-d, < digitalmars-d@puremagic.com> wrote:
>
>> On 2018-07-31 10:12, Manu wrote:
>>
>> > Given your favourite example:
>> > ----
>> > module a;
>> > extern(C++, ns) void foo();
>> > ----
>> > module b;
>> > extern(C++, ns) void foo();
>> > -----
>> > module c;
>> > import a, b;
>> > foo(); // error: ambiguous
>> > ns.foo(); // error, ambiguous (obviously)
>> > a.ns.foo(); // naturally, this works... it's the D module that
>> > correctly organises the symbol. 'ns' is worthless here
>>
>> This works:
>>
>> a.foo();
>>
>> You don't need "ns" in between the module name and the function.
>>
>
> Right... But did you miss the point? The D module does the organisation (as
> you show). The ns offers nothing and creates other kinds of problems.
> Just because name resolution traverses the namespace (in simple cases),
> there is an entire language of complexity that interacts with that name
> lookup, and as far as I know, it has never proven useful, but rather, only
> complicated and annoying leading to boilerplate and hacks in certain
> situations. (ie, this thread exists and many others)

Can you give some examples of those certain situations? It would help clear what is wrong with how it is currently implemented.


One thing I don't like is that the C++ namespaces takes the name. So if you try to import a module that has C++ namespace of the same with the existing module, then you'll get an error. For effectively no reason, because as you say that namespace is useless and just occupies a name that could otherwise be used for the module name.
August 01, 2018
On Tuesday, 31 July 2018 at 23:02:16 UTC, Rubn wrote:
> One thing I don't like is that the C++ namespaces takes the name. So if you try to import a module that has C++ namespace of the same with the existing module, then you'll get an error. For effectively no reason, because as you say that namespace is useless and just occupies a name that could otherwise be used for the module name.

Indeed, case in point: std