Closed seidewitz closed 2 years ago
Let me confirm the commit of https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/commit/715f0b5aaae77abadc991d760a2ef8df58d5ee90 is not included in this PR. Are you ok with this? I think that means invocations of user-defined functions are dropped.
As noted in the PR description:
This PR does not include the implementation of any non-model-level evaluable expressions. The implementation of the evaluation of invocation of user-defined functions (which is not model-level evaluable) is to be handled in ST6RI-599.
Getting user-defined function evaluation right without doing full structural instantiation is proving to be a bit tricky, so I want to get at least the revision to the model-level evaluation done.
Sorry, I missed that. I did git reset --hard
to cancel the previous ST6RI-46. I'll test it.
I'm testing it with CLI interface. First I input:
package EvalTest4 { part p2 { attribute a2 = 2; part p21 { attribute a21 = a2 + 2; } } }
And I tried to evaluate EvalTest4::p2.p21.a21
. But none of the below worked:
%eval EvalTest4::p2.p21.a21
%eval --target EvalTest4::p2 EvalTest4::p2.p21.a21
%eval --target EvalTest4::p2::p21 EvalTest4::p2.p21.a21
How can we successfully evaluate it?
I'm trying to improv the visualizer but I could not deal with such a case, that is, expressions referring to parent's attributes.
FYI, we call evaluate it by manually calling EvaluationUtil.evaluate(a21, null)
but I'm puzzled why it works with setting null
to the target.
This is not working because when you specify a non-null target, the system is trying to find the feature in just that target, and it isn't considering outer scopes. So, when you evaluate with the target EvalTest4::p2::p21
, it is not able to get the value of a2
in a2 + 2
, because that is defined in the outer scope EvalTest3::p2
. If you use a null target, however, the system simply follows the feature reference and checks if it is bound.
Handling nested target contexts, including properly dealing with redefinition, is the tricky bit that I have been addressing for ST6RI-599. Your example works on my local ST6RI-599 branch, but I haven't pushed this update. I started dealing with this to handle chained-feature targets in invocation expressions, but then realized I also had to handle it for evaluating features in general. The latter part also applies for model-level evaluable expressions, so it should really be included here as part of ST6RI-46.
Try it now.
@seidewitz thank you. I confirmed it worked. I updated the visualizer to properly pick up target
in the visualization context. So I think it gives better visualizations. I'll show them in the following comments.
With SHOWINHERITED and EVAL,
package EvalTest1 {
part p1 {
attribute a1 = 1;
part p11 {
attribute a2 = a1 + 1;
}
}
part p11 :> p1 {
attribute a2 = a1 + 2;
part p12 :> p1.p11;
}
}
gives:
To test inherits and outer scopes,
package EvalTest2 {
part p1 {
attribute a1 = 1;
}
part p2 {
attribute a2 = 2;
part p21 :> p1 {
attribute a21 = a1 + a2;
}
}
}
gives:
To test the different inherit contexts,
package EvalTest3 {
part p1 {
attribute a1;
attribute a2 = a1 + 3;
}
part p11 :> p1 {
attribute :>> a1 = 11;
}
part p12 :> p1 {
attribute :>> a1 = 12;
}
}
gives:
To evaluate inherited context with a redefined (bound) outer attribute:
package EvalTest4 {
part p1 {
attribute a1;
attribute a2 = 3;
constraint c11 { attribute b1 = a1 < 2; a1 < 2 }
constraint c12 { a2 < 5 }
}
part p2 :> p1 {
attribute :>> a1 = 1;
attribute :>> a2 = 7;
constraint :>> c12 { a2 < 5}
}
}
gives:
Actually, this still has an issue to evaluate ConstraintUsage c12
. I guess it might be linked with user defined function evaluation.
Finally, I tested it with more practical example:
package EvalTest {
requirement req {
require constraint { 1< 3 }
}
part def Vehicle {
attribute mass;
attribute length = 7.2;
attribute width = 2.8;
part engine : Engine;
constraint weightConstraint {
mass < 1300
}
constraint lengthConstraint {
length < 8.0
}
}
part def Engine {
attribute mass = 200;
}
part vehicle1 : Vehicle {
attribute :>> mass = 1000 + engine.mass;
//attribute :>> mass = 1200;
}
part vehicle2 : Vehicle {
attribute :>> mass = 1500 + engine.mass;
attribute :>> length = 9.0;
}
constraint constraintTest {
vehicle1.mass == 1200
}
requirement def WeightRequirement {
subject v : Vehicle;
attribute totalMaxMass = 1400;
require constraint { v.mass < totalMaxMass }
}
requirement vehicle1Requirement : WeightRequirement {
subject :>> v = vehicle1;
}
requirement vehicle2Requirement : WeightRequirement {
subject :>> v = vehicle2;
}
}
gives:
This also has issues. The first one is the same with EvalTest4
, it cannot evaluate weightConstraint
. The other issue is not related to this PR. But typeOf
relationships from vehicle1.engine
to Engine
are redundant. I guess it's related to inheritance. This should be fixed in ST6RI-601. I'll make a PR after this PR is merged.
@himi
I did some clean up and refactoring on the ModelLevelExpressionEvaluator code. I made sure that all your visualizer evaluation tests still worked. I also took your EvalTest1
through EvalTest4
models and adapted them for use in a Junit ExpressionEvaluationTest
that is now part of the build.
The difficulty with evaluating the constraints is that when you use a syntax like constraint c12 { a2 < 5 }
, the result expression is connected to the result parameter just by a binding connector, not by a feature value, and the evaluation algorithm on this branch does not handle this (I presume you are doing something special to evaluate this expression). This will work better after ST6RI-599 (since a constraint is a predicate, which is really a kind of user-defined function).
For the Junit test, I used the following adaption of EvalTest4
:
package EvalTest4 {
part p1 {
attribute a1;
attribute a2 = 3;
constraint c11 { return result = a1 < 2; }
constraint c12 { return result = a2 < 5; }
}
part p2 :> p1 {
attribute :>> a1 = 1;
attribute :>> a2 = 7;
}
}
and tested on, e.g., p1.c11.result
. But your visualization doesn't seem to show return result parameters on constraints.
I had wrongly filtered ReturnParameterMembership
because it's automatically attached calculations, which are frequently used in SSRs. I changed to filter empty result
only.
This seems to work:
Note: The previous branch in this repository named ST6RI-46 has been deleted. The branch now named ST6RI-46 is a new branch, with all the same commits as the old branch except the last two.
This pull request revises the implementation of model-level expression evaluation in the
org.omg.sysml
project.ExpressionEvaluator
to use the singleton pattern and improves the mechanism for library function implementation.NumericalFunctions::sum
andproduct
as primitive library functions.%eval
magic command that evaluates an expression against previously parsed model resources. The command optionally allows a target to be specified, but this must be given as a qualified name and cannot be a feature chain. The specified target can be a package rather than a type, in which case the package content is imported for the evaluation of the expression, but the effective evaluation target is empty.EVAL
style to the PlantUML-based visualization, which shows the evaluation of feature-value expressions on diagrams.This PR does not include the implementation of any non-model-level evaluable expressions. The implementation of the evaluation of invocation of user-defined functions (which is not model-level evaluable) is to be handled in ST6RI-599.
Note: This description has been updated for changes made based on comments below.