June 10, 2015
On 6/10/2015 5:30 AM, Kenji Hara via Digitalmars-d wrote:
> D has true forward reference resolution mechanism. In that case modules are
> cyclic imported, but the declared symbols don't have actual cyclic references.
> Therefore the snippet should work.

I agree the snippet should work. And I still maintain that cyclical imports are something worth significant effort to avoid.

But also, dmd doesn't quite have a proper mechanism for resolving forward references - it's a series of hacks, which is why it's been such a source of bugs.

The right way to do it is to go full lazy on running semantic() on imported symbols. I did this with enums a while back, and it's been working well.


> https://github.com/D-Programming-Language/dmd/pull/4735

As always, thanks for the quick action!


> And the regression was introduced by your unrelated change. While fixing the
> issue, I couldn't understand why it was necessary.
>
> https://github.com/D-Programming-Language/dmd/commit/a04cf864b932061ad7b72e7cad8b16fabc6a825a

Yeah, it was caused by a hack I put in as yet another hack to deal with forward references.

June 10, 2015
On 6/10/2015 9:03 AM, Andrei Alexandrescu wrote:
> But all of a sudden, people get sugar in their gasoline and sand in their gears
> when they hear of the same thing applied to modules. I suspect it's because some
> legacy languages didn't quite do a stellar job at it. Figuring that stuff out
> and pointing out problems is exactly the kind of thing computers are good at and
> humans, not so good.

I get sand in my gears about it because it's hard to mentally figure out what is happening. Humans, not so good at that.
June 10, 2015
On Wednesday, 10 June 2015 at 17:28:54 UTC, Walter Bright wrote:
> As always, thanks for the quick action!

What would we ever do without Kenji? :)

- Jonathan M Davis
June 10, 2015
On Wednesday, 10 June 2015 at 16:03:17 UTC, Andrei Alexandrescu wrote:
> On 6/10/15 8:41 AM, Brian Rogoff wrote:
>> I agree with you, Walter, that mutual recursion amongst imports is
>> usually bad, but I think you inadvertently made the right decision by
>> allowing it in D, and that the bug should be fixed. If people overuse it
>> to write messy code then the community should tell them to write that
>> code better.
>
> I agree. I'm one of those folks who think circular dependencies are fine, thank you very much, and the few cases in which it causes problems should be flagged and diagnosed in a principled way.
>
> Everybody also likes:
>
> * recursion and mutual recursion of any depth (there's a lot more of it going in the usual programs than one might think)
>
> * recursive and mutually recursive types
>
> * declaring top level names in any order and they just "work"
>
> But all of a sudden, people get sugar in their gasoline and sand in their gears when they hear of the same thing applied to modules. I suspect it's because some legacy languages didn't quite do a stellar job at it. Figuring that stuff out and pointing out problems is exactly the kind of thing computers are good at and humans, not so good.
>
>
> Andrei

Cyclic imports create problems that do not exists with forward declaration. This is surprisingly hard to get a well defined behavior for compile time feature. I would argue to make them illegal, but that is still a good idea to avoid them when possible.
June 10, 2015
On 06/10/2015 11:09 PM, deadalnix wrote:
> On Wednesday, 10 June 2015 at 16:03:17 UTC, Andrei Alexandrescu wrote:
>> On 6/10/15 8:41 AM, Brian Rogoff wrote:
>>> I agree with you, Walter, that mutual recursion amongst imports is
>>> usually bad, but I think you inadvertently made the right decision by
>>> allowing it in D, and that the bug should be fixed. If people overuse it
>>> to write messy code then the community should tell them to write that
>>> code better.
>>
>> I agree. I'm one of those folks who think circular dependencies are
>> fine, thank you very much, and the few cases in which it causes
>> problems should be flagged and diagnosed in a principled way.
>>
>> Everybody also likes:
>>
>> * recursion and mutual recursion of any depth (there's a lot more of
>> it going in the usual programs than one might think)
>>
>> * recursive and mutually recursive types
>>
>> * declaring top level names in any order and they just "work"
>>
>> But all of a sudden, people get sugar in their gasoline and sand in
>> their gears when they hear of the same thing applied to modules. I
>> suspect it's because some legacy languages didn't quite do a stellar
>> job at it. Figuring that stuff out and pointing out problems is
>> exactly the kind of thing computers are good at and humans, not so good.
>>
>>
>> Andrei
>
> Cyclic imports create problems that do not exists with forward
> declaration.

No, they don't. They just preclude the band-aid fix.

> This is surprisingly hard to get a well defined behavior
> for compile time feature.

This is a good thing because it makes reasonably sure the final resolution rules won't take order of declaration into account.

> I would argue to make them illegal, but that
> is still a good idea to avoid them when possible.

That's the lazy way. :o)

I really need to find some time to get back to D frontend implementation.

What does SDC do now?
June 10, 2015
On Wednesday, 10 June 2015 at 21:21:35 UTC, Timon Gehr wrote:
>> Cyclic imports create problems that do not exists with forward
>> declaration.
>
> No, they don't. They just preclude the band-aid fix.
>
>> This is surprisingly hard to get a well defined behavior
>> for compile time feature.
>
> This is a good thing because it makes reasonably sure the final resolution rules won't take order of declaration into account.
>

Well I haven't any solution that is both fast and work with cyclic import in a deterministic manner.

>> I would argue to make them illegal, but that
>> is still a good idea to avoid them when possible.
>
> That's the lazy way. :o)
>
> I really need to find some time to get back to D frontend implementation.
>
> What does SDC do now?

Pretty much what is proposed in DIP31
June 10, 2015
On Wednesday, 10 June 2015 at 21:21:35 UTC, Timon Gehr wrote:
>> I would argue to make them illegal, but that
>> is still a good idea to avoid them when possible.
>
> That's the lazy way. :o)
>

Also, I forgot a not in there. I would NOT prevent it, but still would avoid it in code when possible.
June 10, 2015
On 06/11/2015 12:15 AM, deadalnix wrote:
> On Wednesday, 10 June 2015 at 21:21:35 UTC, Timon Gehr wrote:
>>> I would argue to make them illegal, but that
>>> is still a good idea to avoid them when possible.
>>
>> That's the lazy way. :o)
>>
>
> Also, I forgot a not in there. I would NOT prevent it, but still would
> avoid it in code when possible.

Oh, that's quite relevant. I take back my statement. :)
June 11, 2015
On Wednesday, 10 June 2015 at 17:28:54 UTC, Walter Bright wrote:
> But also, dmd doesn't quite have a proper mechanism for resolving forward references - it's a series of hacks, which is why it's been such a source of bugs.
>
> The right way to do it is to go full lazy on running semantic() on imported symbols. I did this with enums a while back, and it's been working well.

Yes, I've continuously improved the hacky code in dmd, and finally it's almost completed to realize lazy semantic analysis.

List of current implementation details in dmd code:

- before than all, an imported symbol will be set its 'scope' for its lazy semantic analysis.
    Dsymbol::setScope()

- variable types are determined lazily, and it detects 'circular reference' in its initializer.
    v->semantic(v->scope); in DsymbolExp::semantic(), and etc
    v->inuse

- forward reference for functions and on-demand return type inference is done:
    FuncDeclaration::functionSemantic()
        Determine function signatures (parameter types and returnt types)
        If return type is inferred, it will invoke functionSemantic3().
    FuncDeclaration::functionSemantic3()
        Determine function full signature (includind deduced attributes and inferred return types)

- an alias for the symbols comes from instantiations will be resolve lazily
    AliasDeclaration::toAlias()

- an aggregate size (all of field variable types) is analyzed independently from other member semantic (member functions and so on)
    VarDeclaration::setFieldOffset()
    AggregateDeclaration::finalizeSize()

- tangled class template definitions is analyzed correctly.
    ClassDeclaration::baseok

- declarations in static if is lazily resolved
    StaticIfDeclaration::include()
        It will run addMembers() and setScope() for the members, after the condition is correctly evaluated.

- the types and symbols on UDA is lazily resolved
    UserAttributeDeclaration::getAttributes()
        It's called by __traits(getAttributes) to invoke on-demand semantic analysis.
    UserAttributeDeclaration::semantic2()
        UDA does not affect the semantic of annotated symbol, so it's normally deferred until semantic2() stage.

Anymore I cannot say they're just hacks.

While doing them, unfortunately I've introduced not a few numbers of regression issues, but they have been fixed properly.
Remaining issues in HEAD:

https://github.com/D-Programming-Language/dmd/pull/4731
https://github.com/D-Programming-Language/dmd/pull/4738

I'll be happy when you prioritize the PRs.

Kenji Hara
June 11, 2015
On 2015-06-10 18:03, Andrei Alexandrescu wrote:

> * declaring top level names in any order and they just "work"

Even Objective-C has got this feature now.

-- 
/Jacob Carlborg
1 2
Next ›   Last »