How Solver queries name features
A Solver query, the expression you pass to evaluate --expr or check --predicate,
is written in SysML expression syntax, but a qualified name inside it means something
SysML itself has no notation for. This page explains that meaning and why the Solver
needs it.
A qualified name designates a declared feature
In a query, a qualified name such as Catalog::Wheel::mass designates the feature as
it is declared, and the Solver reports the values that feature can take in every
situation the model allows. The feature may belong to a definition that has no usages
at all. Create catalog.sysml:
package Catalog {
part def Wheel {
attribute rimMass = 9;
attribute tyreMass = 3;
attribute mass = rimMass + tyreMass;
}
}
Nothing in this model is typed by Wheel, yet the question “what can a wheel’s mass
be?” has an answer:
syside solver evaluate -i catalog.sysml --expr "Catalog::Wheel::mass"
{
"result": {
"subject": "Catalog",
"expression": "Catalog::Wheel::mass",
"determination": "determined",
"outcome": {
"shape": "attainable_set",
"attainable": {
"values": [
{
"value": "12",
"witness": {
"values": [
["Catalog::Wheel::rimMass", "9"],
["Catalog::Wheel::tyreMass", "3"],
["Catalog::Wheel::mass", "12"]
],
"value": "12"
}
}
],
"exhaustive": "true"
},
"unattainable": { "values": [], "exhaustive": "false" }
},
"causes": []
},
"warnings": [],
"exit_code": 0
}
A path names a feature reached from an arbitrary instance New in v1.0.0
A feature is often reached through other features: the mass of a rocket’s booster,
not the mass of boosters in general. Write that question as a path, Q::f1.f2: the
part before the last :: names a type Q, and the .-separated chain after it is
read from an arbitrary instance of Q. Launch::Rocket::booster.mass means
“booster.mass of an arbitrary Rocket”, whether or not the model contains a usage
typed by Rocket. It is the value the expression booster.mass would have if it
were written inside Rocket.
Create launch.sysml:
package Launch {
private import ScalarValues::Integer;
part def Booster {
attribute dry : Integer = 30;
attribute fuel : Integer;
attribute mass : Integer = dry + fuel;
}
part def Rocket {
part booster : Booster {
attribute redefines fuel = 10;
}
}
}
Every booster weighs dry + fuel, and a rocket’s booster carries 10 units of fuel:
syside solver evaluate -i launch.sysml --expr "Launch::Rocket::booster.mass"
{
"result": {
"subject": "Launch",
"expression": "Launch::Rocket::booster.mass",
"determination": "determined",
"outcome": {
"shape": "attainable_set",
"attainable": {
"values": [
{
"value": "40",
"witness": {
"values": [
["Launch::Rocket::booster.fuel", "10"],
["Launch::Rocket::booster.dry", "30"],
["Launch::Rocket::booster.mass", "40"]
],
"value": "40"
}
}
],
"exhaustive": "true"
},
"unattainable": { "values": [], "exhaustive": "false" }
},
"causes": []
},
"warnings": [],
"exit_code": 0
}
The Solver names every value in its output the same way, so the witness reports
Launch::Rocket::booster.fuel, the fuel of the booster of the arbitrary rocket.
Several paths in one query start from the same instance. In
Launch::Rocket::booster.mass == Launch::Rocket::booster.dry + 10, both sides belong
to one rocket, exactly as they would in an attribute written inside Rocket.
A qualified name through an inherited feature is refused New in v1.0.0
Launch::Rocket::booster::mass looks like the same question, but SysML name
resolution reads it differently. The rocket’s booster declares nothing called
mass: it inherits mass from Booster, and :: resolves an inherited name to the
declaration it came from. As a qualified name, Launch::Rocket::booster::mass is
Launch::Booster::mass, the mass of an arbitrary Booster, whose fuel is anything
at all. Both questions are reasonable, so the Solver takes neither silently:
syside solver evaluate -i launch.sysml --expr "Launch::Rocket::booster::mass"
{
"error": {
"code": "Load",
"span": null,
"message": "'Launch::Rocket::booster::mass' passes through 'mass', which 'Launch::Rocket::booster' inherits without redefining; as a qualified name it means 'Launch::Booster::mass', not a path through 'Launch::Rocket::booster'. Write the question as one of:\n Launch::Rocket::booster.mass (booster.mass of an arbitrary Launch::Rocket)\n Launch::Booster::mass (mass of an arbitrary Launch::Booster)"
},
"exit_code": 2
}
Changed in version 1.0.0: Before 1.0.0, the Solver read such a name as the path, without saying so, and named
every value in its output with :: alone (Launch::Rocket::booster::mass).
The refusal lists every question the name could stand for, each with its reading.
Pick one and rerun. A qualified name whose features are each declared or redefined
by the one before it, such as Catalog::Wheel::mass above, has only one reading and
is accepted as written.
Why the Solver defines its own notation
The question is well defined in SysML v2. A feature declared in a definition is
interpreted over every instance of that definition, whether or not the model contains
a usage of it (KerML 1.0, clause 8.4.3.4). “The values Wheel::mass can take” is
therefore a sound concept.
The SysML v2 specification and its standard library give no notation for it (see
Differences to the Pilot Implementation for how Syside relates to both). A SysML feature reference is
evaluated on an instance: the referenced feature must be accessible from where the
expression is written (KerML 1.0, clauses 8.3.4.8.5 and 8.3.3.3.10). Written at
package level, Catalog::Wheel::mass has no Wheel in context, so as a SysML
expression it is not valid. Chain notation (someWheel.mass) needs an instance to
start from, and adding one would change the model being asked about. No construct in
the specification denotes “this feature, across all instances of its definition”
without introducing an instance.
The Solver therefore defines its own notation. In a query, a qualified name is
resolved by the specification’s ordinary name resolution to a declared feature, and
stands for that feature’s values across all situations the model allows. A path
Q::f1.f2 stands for the values of the chain f1.f2 read from an arbitrary instance
of Q.
Where the notation applies
The notation applies to query text only. Inside a model file, the same text is an
ordinary SysML expression, and Syside validates it as one: Syside 1.0 and later report
feature-reference-expression-access (“Feature reference must be accessible from the
outer scope”) for such a reference. The Solver does not apply that check to the query
you pass on the command line.