Skip to main content

Flex Standard Library

The Flex Standard Library Overview

This page is intended to provide an overview of functionality built into the Flex specification language. Included in this page is documentation on Flex's primitive types, any functionality a user needs to use these types, and an overview of included syntax.

Primitive Types

Flex has a collection of primitive types that are automatically available without any imports. These are as follows:

  • bit -- either true or false
  • intN -- a value from -2^(N-1) to 2^(N-1) - 1 inclusive, where N is a positive integer

Transpiler supported widths: int8, int16, int32, int64

  • uintN -- a value from 0 to 2^N - 1 inclusive, where N is a positive integer

Transpiler supported widths: uint8, uint16, uint32, uint64

  • float32 -- a single precision floating point number as defined by the IEEE 754 standard
  • float64 -- a double precision floating point number as defined by the IEEE 754 standard
  • string -- a sequence of characters (e.g., "foo")

Flex also has several primitive type constructors with special syntax. If T, T0, T1, ..., Tn are arbitrary types, then the following are also types:

  • T[] -- an array of values of type T
  • Optional<T> -- either none or some(t) where t: T
  • (T0, T1, ..., Tn) -- a tuple

For more details see the expressions section.

Built-in Functions

length

function length(x : T[]) -> int32

Returns the length (number of elements) of the array argument.

last

function last(x : T[]) -> T

Returns the last element of the array argument.

Note: fails if the argument array is empty.

range

function range(x : T, y : T, z : T) -> T[]

Returns an array of type T. Valid for int and uint types.

Parameters:

x : lower bound (inclusive)

y : upper bound (exclusive)

z : step size (default is 1)

Examples:

const a : int32[] = range(0,10,2);  == [0,2,4,6,8] : int32
const b : int32[] = range(10,0,-2); == [10,8,6,4,2] : int32
const c : uint8[] = range(2,7);     == [2,3,4,5,6] : uint8
const d : uint8[] = range(5);       == [0,1,2,3,4] : uint8

zip

function zip(as : A[], bs : B[]) -> (A, B)[]

Transforms two lists into a list of pairs.

Note: the resulting list of pairs will have the size of the smallest input list

Example:

 zip([1,2,3], ["a","b","c"]) == [(1,"a"),(2,"b"),(3,"c")]
 zip([a_1, ..., a_n], [b_1, ..., b_m]) == [(a_1,b_1), ..., (a_m, b_m)] // when m <= n
 zip([a_1, ..., a_n], [b_1, ..., b_m]) == [(a_1,b_1), ..., (a_n, b_n)] // when n <= m

enumerate

function enumerate(as : A[]) -> (uint32, A)[]

Transforms a list into a list of pairs, where the first element in each pair is the array index. The index values are returned as uint32.

Example:

 enumerate(["a","b","c"]) == [(0,"a"),(1,"b"),(2,"c")]

float64to32

function float64to32(x : float64) -> float32

Returns the 32 bit version of the argument.

Note: since float64 is has two times the precision of float32 this conversion is an approximation of the original argument.

floor

function floor(x : float64) -> Optional<int64>

Returns the largest possible 64 bit integer value which is less than or equal to the argument.

ceil

function ceil(x : float64) -> Optional<int64>

Returns the smallest possible 64 bit integer value which is greater than or equal to the argument.

abs

function abs(x : int8|int16|int32|int64|float32|float64) -> the_given_type

Returns the absolute value of the argument.

Supported argument types are int8, int16, int32, int64, float32, float64

sin

function sin(x : float64) -> float64

Returns the sine of the argument.

Note: the argument is expected to be in radians.

cos

function cos(x : float64) -> float64

Returns the cosine of the argument.

Note: the argument is expected to be in radians.

tan

function tan(x : float64) -> float64

Returns the tangent of the argument.

Note: the argument is expected to be in radians.

asin

function asin(x : float64) -> float64

Returns the arc sine of the argument.

Note: the argument is expected to be in radians.

acos

function acos(x : float64) -> float64

Returns the arc cosine of the argument.

Note: the argument is expected to be in radians.

atan

function atan(x : float64) -> float64

Returns the arc tangent of the argument.

Note: the argument is expected to be in radians.

atan2

function atan2(y : float64, x: float64) -> float64

Returns the theta component of the point (r, theta) in polar coordinates that corresponds to the point (x, y) in Cartesian coordinates.

Parameters

y: the abscissa coordinate

x: the ordinate coordinate

sqrt

function sqrt(x : float64) -> float64

Returns the square root of the argument.

Note: If sqrt is given a negative argument a failure occurs.

The transpiler is responsible for determining what a failure means in the output language.

pow

function pow(x : float64, y : float64) -> float64

Returns x raised to the power of y.

getOrElse

function getOrElse<T>(x : Optional<T>, y: T) -> T

Returns the v if x is some(v), or a default value y when x is none. Used with optional data types, and value casting. For more details see Casting.

some

Constructor for an the Optional type taking a single argument. For more details see Pattern Matching: Optional Values

Written: some(x) for an x of any type.

none

Constructor for an optional value taking no arguments. For more details see Pattern Matching: Optional Values

Written: none constructing a type Optional<T>

const x : Optional<float64> = none;

Syntax Overview

Further Information

Keywords

const

Declare an immutable global value

Type ascription is required

const x : int32 = 0;

struct

Declare a structured type composed of fields that each have an explicitly declared type

struct Position {
    x : float32;
    y : float32;
}

message

Declare a message type that can be used as a Message in Tangram Pro™, and used as input or output for a transform

Applies to struct declaration

Creates an ontologically significant term to be used in a Transform

message struct Position {
    x : float32;
    y : float32;
}

newtype

Declare a new struct-like type containing a single field

Allows a user to get compile time guarantees about normally non distinct values

Has ontological significance in Flex and can be used as input or output for a transform

newtype Altitude {
    value: int32;
}

variant

Declare a type that can be one of several "variants"

variant Angle {
    DMS(int32, int32, int32);
    Radians(float64);
}

enum

Declare an enumerated type consisting of constants of some declared type

If the type is integral this will be equivalent to enums in C++

enum SimulationStatus int32 {
  Stopped = 0;
  Running = 1;
  Paused = 2;
  Reset = 3;
}

function

Declare a function

function square(x : float64) -> float64 {
    x * x;
}

transform

Declare a transform function that can be used as a Transform in Tangram Pro™ over terms which are ontologically significant.

transform Celsius2Fahrenheit(c : Celsius) -> Fahrenheit =
  Fahrenheit {
    temp = c.temp * 9.0 / 5.0 + 32.0;
  };

let

Bind a value to an identifier

Values bound like this are immutable

Type is optional when it can be inferred

let x = 1.0 : float32;
x + 1.0;

let x : float32 = 1.0;
x + 1.0;

match

Pattern matching control flow

match(optional_value) {
    some(value) => value;
    none => default;
}

assert

Refinement of data and specification of correctness properties

message struct Position {
    x : float32;
    y : float32;
    assert x > 0.0 and x < 10.0;
    assert y > 0.0;
}

let x : int32 = {
  assert x > 0;
  x + 1;
}

for

Used in the list comprehension syntax

Constructs a new list using each value of a pre-existing list

const xs: uint8[] = [2,4,6,20];
const xsPlusOne: = [x + 1 for x in xs]
//              ~> [3, 5, 7, 21]: uint8[]
const ys: uint8[] = [2,4,6,20,21];
const evens = [y + 1 for x in ys if y % 2 == 0]
//         ~> [2,4,6,20]

scan

Used to define operations over a collection

An accumulation value is defined to the right of the scan keyword and it's initial value is set

Returns a list of intermediate and final values of the accumulator

const sums: uint8[] = [cumulSum for x in [2,4,6,8] scan cumulSum: uint8 = 0 in cumulSum + x]
//                 ~> [2, 6, 12, 20]: uint8[]

fold

Used to iterate over the items in an array to build up a new value

function sumNums(xs: int32[]) -> int32 {
   fold(sum = 0; x in xs) {
     sum + x;
   };
}

try

Lift a potentially partial value, i.e. code that could throw an exception once transpiled, to Optional. See the section of pattern matching on Optional values for how to use the resulting value.

function safeDivide(num: int32, den: int32) -> Optional<int32> {
    try(num / den);
}

filter

Used to filter items in an array. It returns a new array containing the items where the filter body is true.

function evens(xs: int32[]) -> int32[] {
  filter(x in xs) { 
    x % 2 == 0; 
  };
}

Operators

  • Arithmetic: +, -, /, *, % Defined for numeric types
  • Comparison: <, >, <=, >= Defined for numeric types
  • Equality: ==, != Defined for primitive types that are not type constructors
  • Boolean: &&, ||, ! Defined for bit
  • Bitwise: &, |, ~, ^ (Xor) Defined for bit, intN, uintN
  • Bit shift: << (left), >> (right) Defined for intN, uintN

Literals

  • Bit literals are true and false
  • String literals are delimited by double quotes. "This is a string"
  • Floating literals contain a decimal point. 1.618 and 0.05 are valid, whereas 1, 1. and .05 are invalid
  • Type ascription is allowed for any flex expression. x : T for some type T and value x
  • Array literals are delimited with square brackets. [1,2,3] : int32[]
  • Tuple literals are delimited with parentheses. (1,false,"foo") : (int32,bit,string)
  • Hexadecimal literals begin with 0x
  • Binary literals begin with 0b
  • Integers can be represented as 0 in intN and uintN

Types must be able to be inferred for integer literals or explicitly ascribed

  • Underscores _ can be used in numeric literals as digit separators. 1_000_000 is equivalent to 1000000