Sinelabore Homepage

Attributes#

Role in SysML v2#

An attribute definition defines a set of data values, such as numbers, quantitative values with units, qualitative values such as text strings, or data structures of such values.

An attribute usage is a usage of an attribute definition.

Mapping to C++#

Basic attribute definitions without nested attributes are represented as structs.

Attributes with nested attributes are represented as classes.

Attribute usages typically occur within parts (and can also be package-scoped — see Packages).

Attributes can have default values and a type. If no type is given the type is mapped to an int and set to 0 as default value.

Attributes (and items) may declare multiplicity, for example attribute test : Integer[0..5];. Indexed access in actions uses #(n) where supported.

When a part specializes another, attributes can be redefined with :>> or redefines (see Parts).

Units#

An attribute value may carry a unit in square brackets. All of these notations are accepted:

private import ScalarValues::*;
private import SI::*;                 // needed for the unqualified spellings below

part def Measurements {
    attribute qualified : Real = 2.2 [SI::W];               // qualified name
    attribute plain     : Real = 100 [kg];                  // unqualified
    attribute symbol    : Real = 47 ['Ω'];                  // symbol, as an unrestricted name
    attribute quotient  : Real = 12 [km/h];                 // quotient
    attribute product   : Real = 5 [SI::kilo*SI::metre];    // prefix times unit
}

The unqualified forms (kg, km/h, 'Ω') only resolve if the unit names are in scope. Either write them qualified ([SI::kilogram]) or add private import SI::*;. Without that import, SysML editors and the reference implementation report the names as unresolved, even though the Sinelabore parser accepts them.

Normalization, not conversion#

Units are normalized, so different spellings of the same unit compare equal: km, SI::km and SI::kilo*SI::metre all reduce to the same canonical form, and so do 'Ω' and SI::ohm.

Values are not converted. The generated C++ keeps the numbers you wrote:

attribute mixedScale : Real := 5 [km] + 200 [m];   // becomes 5 + 200, not 5200

Because that is easy to overlook, the generator reports it:

W3115: 'mixedScale' adds values with different units ('km' and 'm').
       Units are not converted; the generated code combines the plain numbers.

The warning is deliberately limited to + and -. Mixing units under * and / is ordinary physics — electrical power is volts times amperes — so those stay quiet:

attribute power    : Real := 12.0 [SI::V] * 2.5 [SI::A];    // no warning
attribute velocity : Real := 100.0 [SI::m] / 9.58 [SI::s];  // no warning
attribute sameUnit : Real := 5 [m] + 200 [m];               // no warning

If you need real unit arithmetic, scale the values in the model yourself — for example by writing both operands in the same unit.

Example#

SysML v2 source code:


private import ScalarValues::*;

package Test {
	
	/*
	* Another comment
	*/
	attribute def Att4{
		attribute att5 : Integer default 10; 
		attribute att6 : Real default 7.0;
	}


	// comment
	part def apart{
		attribute att10 : String default "Hello"; 
		attribute b:Integer default 3;
		attribute att3 : Boolean;
		attribute samples : Integer[0..5];
		
    // attribute with user-defined type
    attribute f:Att4;
  }

}

C++ source code:


namespace Test {

class Att4 {
public:
  int att5;
  double att6;

  // Constructors
  Att4(int att5Val, double att6Val) : att5(att5Val), att6(att6Val) {}

  Att4() : att5(10), att6(7.0) {}
};

struct Att28 {};

class apart : public Part {

public:
  apart() {}

  // elements of this part

  std::string att10 = "Hello";
  int b = 3;
  bool att3 = false;
  Att4 f;
  int x = 0;

  virtual void process() override {}

  // must be called by derived classes after constructing the parts
  virtual void init(void) override {}
};