Skip to content

Scalar flow

Leon Starr edited this page Nov 6, 2023 · 3 revisions

A scalar flow is similar to the familiar typed programming language variable. The term scalar, in this context, indicates that a corresponding value appears to be atomic from a relational point of view. The only way to get at any internal structure is through the use of type specific (non-relational) operations.

The type definition system for scalars is entirely orthogonal to the xUML modeling language. Once defined, a type may be associated with one or more attributes in the class model.

Relatively unconstrained mathematical types such as Boolean, Integer, Rational and String are available as foundational types. These are used as a basis for specifying more constrained types. Whereas the set of all possible String values of a given maximum length is quite large, the set of all legal ICAO Airport Codes is much more constrained. So a type like ICAO Airport Code could be defined as a constraint on the base type String.

There is no limit to the complexity or structure of an unconstrained type. You could, for example, define a type called Video Image if you like.

Note that a scalar is defined not just by defining a set of values and a structure. Operations supported by the type must also be defined.

If you have a sufficiently complex type that supports an extensive set of operations on values of that type you might consider modeling it out in some domain.

Scalar value assignment

Use the = assignment operator to assign and implicitly declare a labeled scalar flow.

cabin location = /R1/Cabin.Floor

Here, the type defined for the Cabin.Floor attribute establishes the type of the cabin location scalar flow. We know it is a scalar variable because the = assignment operator was used.

If the RHS specifies an attribute of a class, you must ensure that a single instance (not zero or many) is selected, otherwise a fatal error occurs. If, for example, the relationship to Cabin across R1 is 0..1, an error will occur.

It is the modeler’s responsibility to take the class model into account when writing action language. In the case of a 0..1 access, it is important to consider both cardinalities. Otherwise, the modeler can refactor the class model to eliminate the 0..1 access via an association class or a generalization. But there are certainly cases where the modeler may wish to retain the 0..1 access.

A smart action language editor can catch this error prior to runtime by examining the class model.

There are two ways to handle this conditionality in Scrall.

/R1/Cabin ? {
   x = /R1/Cabin.Floor
   // other actions
} : {
    // no cabin case actions
}

Or:

my cabin .= /R1/Cabin
my cabin? {
   // just use my cabin.Floor instead of x
} : {
   // no cabin case
}

Another common case of implicit assignment is via input parameters. Here we assume that there is one integer input i, one real input r, and one PSI pressure value.

x = ^r  // x is inferred as rational since the parameter ^r is typed as a rational number
i = ^i // i is typed integer since input parameter i is typed as integer
c = ^pressure // c is PSI to match the input parameter PSI scalar

Scalar component access

Now consider a Point and a Rectangle data type. ThePoint data type has two components X and Y, each of type Position. The Rectangle data type has components Origin of type Point and Length and Width each of type Distance.

A component, computed value or operation made publicly available on this scalar may be accessed using dot notation.

rects origin = rect.Origin  // Assigns Origin component

In the example above the Origin component is extracted and assigned to the variable rects origin. Since the component is typed as Point, the assignment sets the variable to the same type.

If the LHS flow was previously explicitly or implicitly defined as some other type, there will be an error on this assignment.

x, y = rect.Origin(X, Y)

Note that compoent order is signficant. So, this is also legal:

y, x = rect.Origin(Y, X)

In either of the previous two examples, the LHS variables will each assume the Position type.

Explicit scalar declaration

Any variable not currently in use may be introduced with an explicit type.

There are a few cases where explicit definition of a type is required. Use the :: symbol to associate a type with a scalar variable. It is required, for example, when you want to assign multiple attribute values. Consider a Point type that has components X and Y, each of type Real.

pt::Point(X: ^x, Y: ^y)

In the example above, two input parameters are assigned using the Point type’s init operation.

When a scalar variable is explicitly declared it must be assigned a complete value. Uninitialized or partially initialized variables will trigger a fatal error.

pt::Point(x: in.x, y: in.y)  // Correctly initialized
pt2::Point // Also ok, gets default initial value

Also you can define multiple variables in one line if they are of the same type:

pt1, pt2::Point(x: ^x, y: ^y) // both initialized to the same values

In the above example pt1 and pt2 are both initialized to the same value.

Introduction

Model semantics

Flows (as Variables)

Constants and literals

Structure of an activity

Accessing the class model

Data flow


Grammar and parsing notes

Components

Clone this wiki locally