Systems-Modeling / SysML-v2-Pilot-Implementation

Proof-of-concept pilot implementation of the SysML v2 textual notation and visualization
GNU Lesser General Public License v3.0
128 stars 24 forks source link

ST6RI-626 Feature chains with intermediate redefinitions evaluate incorrectly #435

Closed seidewitz closed 1 year ago

seidewitz commented 1 year ago

Feature chains in which intermediate features are redefined were evaluated incorrectly. For example, in the model

part def A {
    attribute z;
}
part x {
    part a = b;
    part b : A {
        attribute :>> z = 0;
    }
}
part y :> x {
    part :>> b {
        attribute :>> z = 1;
    }
}

evaluating y.a.z resulted in 0, while 1 would be expected due to the redefinition of b::z in y. This update corrects that.

himi commented 1 year ago

Hmmm... It's quite complicated issue. The visualizer is screwed up with this case: Screenshot 2022-12-11 at 12 48 55 AM

This is because evaluating y.a.z by the visualizer is actually evaluating x::b::z instead of the redefined one, y::b::z. Can getInheritedMembership() take such redefinitions into account?

seidewitz commented 1 year ago

Can getInheritedMembership() take such redefinitions into account?

The inherited y::a is literally the same element as x::a, so there is no way that a call to getInheritedMembership can make tell if the parent namespace context is y or x. That's why feature chains were introduced, so y.a can be distinguished from x.a.

Note that the sample model I included in the PR description is actually not right because x::b::z is already bound to 0, so it can't consistently be redefined to be bound to 1. Rather, x::b::z should have a default of 0, in which case it is OK to redefine it to be bound to 1. It then also makes sense that z can have different values than its default in different inheritance context.

To take this into account, I don't think it is enough just to evaluate the feature value expression for a feature displayed on the diagram. Rather, you need to evaluate the correct feature chain to that feature, and the evaluator will then find the correct expression to evaluate. For example, if you are displaying the inherited ^z in a symbol for the inherited ^a feature of y, then you need to evaluate the feature chain y.a.z, which, given the update in this PR, would return the correct value. Then you would display something like

^zdefault0:>> A::z➞ 1

where the static declaration is exactly as for x::a::z, but the evaluation gives a different value than the default.

But I would think that a change like this should probably be put on the backlog in a new issue, and perhaps handled in the next sprint.

himi commented 1 year ago

Oh I forgot getInheritedMembership() could not get the context of y. So I need something to resolve y.a.z is actually y::b::z rather than x::b::z by taking a = b binding into account. I tested the following model:

package 'EvalTest-FC' {
    part def A {
        attribute z;
    }
    part x {
        part a = b;
        part b : A {
            attribute :>> z = 0;
        }
    }
    part y :> x {
        attribute v = a.z;
        part :>> b {
            attribute :>> z = 1;
        }
    }
}

and it gives:

Screenshot 2022-12-12 at 8 41 47 PM

The result looks somewhat contradicting, but as you said, z = 0 should be z defaults 0. I'll deal with to correctly evaluate such features in the future.