User talk:Schuetzm/scope2

From D Wiki
< User talk:Schuetzm
Revision as of 22:17, 27 February 2015 by Schuetzm (talk | contribs) (Created page with "== Example for the inference algorithm == Applied to the function deadalnix used to demonstrate the rvalue/lvalue problem: (1) <code>foo()</code> is <code>@safe</code>, maki...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Example for the inference algorithm

Applied to the function deadalnix used to demonstrate the rvalue/lvalue problem:

(1) foo() is @safe, making its param scoped:

void foo(scope int** a) {
    // no inference for `a`
    // ("mystery scope" in your terms)
    // => SCOPE(a) := [a] (final)
    int** b = a;
    // first assignment to `b`:
    // => SCOPE(b) |= SCOPE(a) = [a] (incomplete)
    int d;
    int* c = &d;
    // only access to `&d`:
    // => SCOPE(&d) := [d] (final)
    // assignment to `c`:
    // => SCOPE(c) := SCOPE(&d) = [d] (incomplete)
    *b = c;
    // assignment from `c`:
    // => SCOPE(c) |= SCOPE(*b)
    // => DEFER because SCOPE(*b) = SCOPE(b) is incomplete
    // assignment to `*b`:
    // (treated as assignment to all vars in the lvalue)
    // => SCOPE(b) |= SCOPE(c)
    // => DEFER because SCOPE(c) is incomplete
    // ---------------------------------------------------
    // we now have:
    // SCOPE(a) = [a]
    // SCOPE(b) = [a]
    // SCOPE(c) = [d]
    // unresolved:
    // SCOPE(b) |= SCOPE(c)
    // SCOPE(c) |= SCOPE(b)
    // break cycles:
    // UNION(b, c)
    // tmp := SCOPE(b) | SCOPE(d) = [a] | [d] = [a]
    // SCOPE(b) := tmp = [a]
    // SCOPE(c) := tmp = [a]
    // => all resolved
    // ---------------------------------------------------
    // validate dependencies:
    // a: [a] <= [a]    // OK
    // b: [b] <= [a]    // OK
    // c: [c] <= [a]    // OK
    // => ok, all depending on higher scopes
    // ---------------------------------------------------
    // => satisfiable, now let's check the assignments:

    int** b = a;        // [a] <= [a]   => OK
    int d;
    int* c = &d;        // [a] > [c]    => BAD
    *b = c;             // [a] > [c]    => BAD
    // => invalid assignments
    // note how it even traces where the bad value comes from
}

(2) foo() is in a template, param scope gets inferred

void foo(T)(T** a) {
    // start with empty scope for `a`
    // => SCOPE(a) := [] (incomplete)
    T** b = a;
    // only access to `a`:
    // => SCOPE(a) |= SCOPE(b)
    // => DEFER because SCOPE(b) is incomplete
    // first assignment to `b`:
    // => SCOPE(b) |= SCOPE(a)
    // => DEFER because SCOPE(a) is incomplete
    T d;
    T* c = &d;
    // only access to `&d`:
    // => SCOPE(&d) := [d] (final)
    // assignment to `c`:
    // => SCOPE(c) := SCOPE(&d) = [d] (incomplete)
    *b = c;
    // assignment from `c`:
    // => SCOPE(c) |= SCOPE(*b)
    // => DEFER because SCOPE(*b) = SCOPE(b) is incomplete
    // assignment to `b`:
    // (treated as assignment to all vars in the lvalue)
    // => SCOPE(b) |= SCOPE(c)
    // => DEFER because SCOPE(c) is incomplete
    // ---------------------------------------------------
    // we now have:
    // SCOPE(a) = []
    // SCOPE(b) = []
    // SCOPE(c) = [d]
    // unresolved:
    // SCOPE(a) |= SCOPE(b)
    // SCOPE(b) |= SCOPE(a)
    // SCOPE(b) |= SCOPE(c)
    // SCOPE(c) |= SCOPE(b)
    // break cycles:
    // UNION(a, b, c)
    // tmp := SCOPE(a) | SCOPE(b) | SCOPE(c) = [] | [] | [d] = [d]
    // SCOPE(a) := tmp = [d]
    // SCOPE(b) := tmp = [d]
    // SCOPE(c) := tmp = [d]
    // => all resolved
    // ---------------------------------------------------
    // validate dependencies:
    // a: [a] > [d]     // BAD
    // b: [b] > [d]     // BAD
    // c: [c] <= [d]    // OK
    // => not ok, there are vars depending on lower (or disjunct) scopes
    // ---------------------------------------------------
    // => not satisfiable
}