Skip to main content

Introduction to Flex

Flex is a specification language that allows you to define message data types and transform functions for component software interfaces. From Flex specifications, Tangram Pro generates consistent interface libraries in C++ and other languages, even as your system design changes. To facilitate broad compatibility we are limiting C++ usage to the C++11 standard.

Tangram Pro provides a Flex Editor and Package Manager that allows you to write code in your web browser with an interactive development experience, along with versioning and package management.

Additional Resources

Example Flex File

To introduce the Flex language, we will use an example similar to the one found in Author a Transform with Flex. The Flex code below should be found in the file MyExamplePackage_v1/MyExampleModule.flex.

module Tangram::MyExamplePackage.MyExampleModule

import Tangram::MyHelpfulConstants.ConversionFactors (feet2meters)
import Tangram::MyHelpfulConstants.Approximations as Approx

const pi: float64 = Approx.PI_8PLACES;

// A position using imperial units
message struct PositionUS {
    latitudeDegrees: float64;
    longitudeDegrees: float64;
    altitudeFeet: float32;
}

// A position using metric units
message struct PositionMetric {
    latitudeRadians: float64;
    longitudeRadians: float64;
    altitudeMeters: float32;
}

/* Convert a position that uses imperial units into a position
 * that uses metric units.
 */
transform US_to_Metric(i : PositionUS) -> PositionMetric {
    let degrees2radians = pi / 180.0;
    PositionMetric {
        latitudeRadians = i.latitudeDegrees * degrees2radians;
        longitudeRadians = i.longitudeDegrees * degrees2radians;
        altitudeMeters = i.altitudeFeet * feet2meters;
    };
}

The standard unit of Flex code is called a package (e.g., MyExamplePackage::v1). Flex packages can be published in Tangram ProTM and depend on other packages. A single package corresponds to a folder in the file system. Within a package are zero or more modules (e.g., MyExampleModule), each contained in its own separate file with the .flex extension. A module file should begin with a module header followed by zero or more import statements followed by a list of declarations.

Minor Notes
  • Flex supports single line // and multi-line /* */ comments.
  • Identifiers may contain alphanumeric characters and underscores. They must begin with a letter or underscore.
  • Identifiers are case-sensitive.

Import Statements

An import statement brings other modules and declarations therein into this module's scope. There are two forms of import statement:

import PACKAGE_NAME.MODULE_NAME (DECL1, DECL2, ...);
import PACKAGE_NAME.MODULE_NAME as ALIAS;

The first form directly imports the declarations listed in the parentheses. In other words, DECL1 and DECL2 can now be referenced elsewhere in this module. The second form imports another module and establishes an alias to refer to it. A declaration named MYDECL in PACKAGE_NAME.MODULE_NAME is now accessible as ALIAS.MYDECL.

Wildcard Imports

Flex does not include a "wildcard" import that directly imports all declarations in a module. This is so that the definitions of all identifiers can be easily found.

Declarations

The rest of a Flex module, after the imports, is a list of declarations. A declaration can define a data type, transform, function, or constant. In the example above, pi, PositionUS, PositionMetric, and US_to_Metric are declarations.

The order in which the declarations appear is unimportant. Although it is generally good practice to place a declaration before its uses. For this reason, US_to_Metric appears last in the example since its definition refers to the other three declarations.

Data Type Declarations

See section Data Types.

Flex's user-defined data types include structs, enums, variants, newtypes and type aliases.

Transforms and Functions

See section Transforms

Transforms describe conversions between data types of a message standard. The message keyword indicates that a data type is part of a message standard, and thus is a valid input or output type of a transform. While the syntax of transforms is intended to be familiar to C++ and Java programmers, the semantics are designed to be amenable to formal verification and program transformation.

Constants

A const definition binds an expression to an identifier. In the example above, Approx.PI_8PLACES is bound to the identifier pi. Note that Flex does not have mutable state, so a const definition says that the identifier "is precisely equal to" or "can be replaced with" its definition. It is not a variable or place in memory that contains a value, and its value cannot be changed.

const NAME: TYPE = EXPRESSION;
Syntax Overview