Skip to main content

builtin functions

The fixed library of functions every module already has. There is no import and no backing declaration; they are called like any other function.

const bearings_deg: int32[] = [10, 45, 90];

const count: uint32 = length(bearings_deg);
const widest_deg: int32 = last(bearings_deg);

Names​

These names are built in: length, last, range, zip, enumerate, float64to32, floor, ceil, abs, sin, cos, tan, asin, acos, atan, atan2, sqrt, pow, getOrElse, serialize, and substring.

  • A declaration cannot take one of these names.
  • Arity and argument types are checked per function, and a mismatch is one diagnostic whatever the function.
  • A few are polymorphic over an element type. That polymorphism belongs to the built-ins only, and Flex has no generics of its own.
There Is No Standard Library

These names are the whole library, and nothing extends them: an import reaches only modules of your own project.

Collections​

  • length(xs: T[]) -> uint32 — the element count, always uint32 whatever T is.
  • last(xs: T[]) -> T — the final element. An empty array is a runtime failure.
  • range(end), range(start, end), range(start, end, step) — an integer array. Every argument is the same integer type, and the result is an array of it.
  • zip(as: A[], bs: B[]) -> (A, B)[] — element-wise pairing, as long as the shorter input.
  • enumerate(xs: T[]) -> (uint32, T)[] — each element paired with its index, from 0.

range treats end as exclusive. The one-argument form starts at 0 and steps by 1, the two-argument form steps by 1, and a step that never reaches end gives an empty array. A step of 0 is a runtime failure.

const callsigns: string[] = ["Viper-1", "Hawk-2"];
const bearings_deg: int32[] = [10, 45, 90];

length(callsigns)                                 // => 2
last(bearings_deg)                                // => 90
range((4: uint8))                                 // => [0, 1, 2, 3]
range((0: int32), (360: int32), (90: int32))      // => [0, 90, 180, 270]
zip(bearings_deg, callsigns)                      // => [(10, "Viper-1"), (45, "Hawk-2")]
enumerate(callsigns)                              // => [(0, "Viper-1"), (1, "Hawk-2")]
try(last([]: int32[]))                            // => none

Numbers​

  • abs(x: T) -> T — absolute value for any numeric T. On an unsigned type it is the identity.
  • floor(x: float64) -> Optional<int64> — the largest integer at or below x, absent when that does not fit in an int64.
  • ceil(x: float64) -> Optional<int64> — the smallest integer at or above x, absent on the same terms.
  • float64to32(x: float64) -> float32 — the narrowing to the nearest float32. It is the only supported route between the float types.
  • sqrt(x: float64) -> float64 — the square root. A negative argument gives NaN rather than failing.
  • pow(x: float64, y: float64) -> float64 — x raised to y.
  • serialize(x: T) -> uint8[] — the big-endian bytes of a numeric value.

serialize needs a type that has a byte width: an intN or uintN whose width is a multiple of 8, a float32, or a float64. An intN/uintN gives N/8 bytes most-significant first, and a float gives the bytes of its IEEE-754 pattern. Anything else is rejected at check time, because both the type and the width are already known.

abs((-120: int32))                    // => 120
abs((120: uint32))                    // => 120
floor((87.6: float64))                // => some(87)
floor((-2.3: float64))                // => some(-3)
ceil((87.2: float64))                 // => some(88)
float64to32((87.5: float64))          // => 87.5
sqrt((16.0: float64))                 // => 4
pow((2.0: float64), (8.0: float64))   // => 256
serialize((0x0102: uint16))           // => [1, 2]
serialize((-1: int8))                 // => [255]
serialize((87.5: float32))            // => [66, 175, 0, 0]

Trigonometry​

  • sin(x: float64) -> float64, cos(x: float64) -> float64, tan(x: float64) -> float64 — the argument is in radians.
  • asin(x: float64) -> float64, acos(x: float64) -> float64, atan(x: float64) -> float64 — the result is in radians.
  • atan2(y: float64, x: float64) -> float64 — the polar angle of (x, y), in radians over (-π, π].

asin and acos outside [-1.0, 1.0] give NaN, which is a value and not a failure. atan2 takes the ordinate first and the abscissa second.

cos((0.0: float64))                            // => 1
asin((1.0: float64))                           // => 1.5707963267948966
atan2((1.0: float64), (1.0: float64))          // => 0.7853981633974483
try(asin((2.0: float64)))                      // => some(NaN)

Optionals​

  • getOrElse(x: Optional<T>, fallback: T) -> T — the contained value, or the fallback when there is none.

The first argument must be an Optional, and the fallback must be its inner type.

getOrElse(some((512: uint16)), 0)                  // => 512
getOrElse((none: Optional<uint16>), (0: uint16))   // => 0

Strings​

  • substring(s: string, start: uint32, end: uint32) -> string — the characters over the half-open range [start, end).

Both indices are integer types. A start past end, or an end past the length of the string, is a runtime failure.

substring("GroundStation-1", 0, 6)         // => "Ground"
substring("Viper-1", 6, 7)                 // => "1"
try(substring("Viper-1", 0, 99))           // => none

Errors​

Taking a built-in name for a declaration​

const length: uint32 = 3;   // error: reserved-builtin-name

An argument of the wrong type​

const count: uint32 = length((42: int32));   // error: builtin-call-args

The wrong number of arguments​

const count: uint32 = length([(1: int32), 2], [(3: int32)]);   // error: builtin-call-args

Serializing something with no byte width​

const bytes: uint8[] = serialize("Viper-1");   // error: builtin-call-args

Serializing a width that is not a whole number of bytes​

const bytes: uint8[] = serialize((1: uint7));   // error: builtin-call-args
  • function — the declaration a built-in name cannot take, and the call form these share.
  • value_cast — the numeric conversions that are forms rather than functions.
  • array — the collections most of these take.
  • optional — what floor, ceil, and getOrElse deal in.