On Wed, 29 Apr 2009 04:26:55 -0400, Denis Koroskin <[email protected]> wrote:
On Tue, 28 Apr 2009 23:06:32 +0400, Robert Jacques <[email protected]>
┌───────┬──────────────┬────────────────────┬─────────────┐
│ scope │ Common Super │ Unknown Allocation │ Transitive† │
└───────┴──────────────┴────────────────────┴─────────────┘
Use of the scope keyword for the common ownership-type is based upon Walter’s original escape analysis blog. However, this design is based upon using the type system restrictions as opposed to full escape analysis to prevent object escape. Full escape analysis would alleviate the restrictions in rule 6.
Basic Rules:
1) Refers to scope definitions inside a function body.
2) May only be assigned at declaration
        scope Node!(int) n;
        n.next = new Node!(int)(); // Error: Possible escape
n = n.next; // Error: see relaxation of this rule below

What's Node? Is it a class or a struct?

Opps. Class. I've updated the wiki4D page with
scope Node!(int) n = mySharedNode;

I believe you should have put Node's definition, first, and explained and implicit ctor call, if one takes place.

Okay.

3) Applies to references taken from scope types
        scope int* value = &(n.value);

So, scope T and scope T* have different meaning?

scope T means that T is constructed on stack, but scope T* is essentially "a pointer to scope variable". If that's the case, it is *very* confusing, because one could expect scope T to be the same no matter T is a class, a struct or a primitive type like int or ptr.

No, your confusion stems from Walter's choice to reuse the scope keyword, yet again.
Logically,
scope T  -> scope(T)
scope T* -> scope(T*)
As scope is transitive.

It would be better to write

scope(int)* value = &(n.value);

Now it's more clear that value is a pointer to a data of type int which is stored on stack. I believe that's what intended in your example.

Though this is also correct. (Wiki code example updated)

4) Implicit conversion is always fully transitive.
        Foo[] y;
        scope Foo[]  x = y;

I don't understand what this example does.
5) Mixed implicit conversion is illegal.
        scope(Foo)[] z = y; // Error: cannot implicitly convert...

Rule 4 and 5 have to do with the ways arrays can create loopholes in the type system (Bug 2095, http://d.puremagic.com/issues/show_bug.cgi?id=2095)
Adding a link in the wiki.

4) Objects and structs use the local interface
f.push(5); // Error: push is not part of the scope interface temp.push(5); // Okay, push is part of the local interface


I don't understand this example. What's the difference between temp and f? They all said to be the same (see example 1). What's a difinition of push, anyway? *Please*, provide class difinition, first.

Opps. My example is completly wrong. *Sigh* How's this.

auto sf = new auto(Stack!(Foo))(); // declared as class Stack(T) {}, stack interface defaults
auto f1 = new Foo();
auto f2 = new auto(Foo)();
sf.push(f1);                        // Okay,  push(local Foo) is defined
sf.push(f2); // Error: push(stack Foo) is is not defined, use a scope class declaration instead

And I need to work on clearer examples...

Note that this catches all of Walter’s examples from the Escape Analysis blog via rule 3:
        int* foo()
        {
            int x = 3;
return &x; // Error: can not convert type auto(int)* to int*
        }

        int* bar(int* p) { return p; }
        int* foo()
        {
            int x = 3;
            return bar(&x);             // Error: ditto
        }

        void abc(int x, int** p) { *p = &x; } // Error: ditto


I don't see *any* difference between scope and stack variables. Besides, both using the same keyword, scope, and essentially are the same. It's very confusing because I got no idea about the difference between them, aside from scope object being created automagically and stack object need to be constructed explicitly:

scope Node!(int) n; // scope
scope Foo foo = new Foo(); // stack

All I can say, wtf?

Honestly, I seriously though of using final instead of scope to avoid just this confusion. But I decided to follow Walter's choice. (Besides it's more intuitive).

scope Foo foo = new Foo(); // Foo is a of type scope and has been allocated on the stack. (see rule 1) auto Foo f2 = new scope(Foo)(); // Foo is a of type stack and has been allocated on the stack. (see rule 1)

I think scope Foo foo = new Foo(); should be probably be deprecated. (which I hinted at in the class definition section)

The proposal sound reasonable, but it's hard to follow. I really can't comment on it because I didn't fully understand it.

Many of my coworkers are preparing for an upcoming Game Developers Conference (КРИ, Russia) and we listen to the their talks everyday, spot errors, make some suggestions etc. And almost everyone does the same mistake: they explain solution without explaining a problem. It is very important but *really* hard to understand *why* you do something when you don't know what's a problem is.

I believe your proposal suffers from it, too. For example, when reading an introduction, I see this:

┌──────────────┐
│ Overview     │
├──────────────┼─────────────────┬─────────────┬──────────────┐
│ Hierarchy    │ Description     │ Ownership   │ Transitivity │
├──────────────┼─────────────────┼─────────────┼──────────────┤
│ scope        │ super-interface │ unknown     │ deep†        │
│  ││└─stack   │ current scope   │ stack       │ implicit     │
│  │└──local   │ object default  │ local-heap  │ deep†        │
│  ├───shared  │ thread safe     │ shared-heap │ deep†        │
│  └───mobile  │ unique objects  │ shared-heap │ shallow      │
└──────────────┴─────────────────┴─────────────┴──────────────┘

You tell that you introduce 5 different qualifiers but you don't explain why are they needed. Why not 4, not 3? What problem each of them solve? All I can do is guess and be proven wrong, that's the most frustrating.
Next, you tell about issues:

•scope(T) in a function body conflicts with scope guard statements. This is a general problem with Walter’s choice of using the scope keyword for this concept. A clean solution is to mandate the use of {} in scope guard statements. Others include using an alternative keyword(auto, final, scope!(exit)), let the ambiguity stand, add a keyword, etc.

Great! You never told that "scope" keyword is used by your proposal. Without showing any line of code, it's absolutely worthless to mention keyword conflict. Issues belongs to "pros and cons" section at the end of your proposal, just before a conclusion.

I also didn't understand a difference between scope and stack - that's pretty much all you explained! You gave no example of shared or mobile object, how they are used, how ownership passing occurs etc. I expected to see a rationale of these qualifiers, but there is no one.

cents += 2;


Thanks a lot for the comments. They a really appreciated. I see I need to go back and do some rewriting.

Reply via email to