Note: None of this capability is currently implemented.
The standard integer and float types (e.g., i32, f64) were introduced early in this reference, so that we could show examples of working expressions and code. Now we can reveal that these types are defined in the standard library using a more primitive number type.
This page covers:
- The primitive number types: int and float
- enum types
- How to define additional number types beyond the standard collection
The 'int' and 'float' number types
int-32 specifies a 32-bit integer. Any integer value from 1 to 128 may be specified after the dash, to establish the number of bits.
Similarly, float-32 is a 32-bit floating point number. Floats only support 32 and 64-bit values.
Unlike i32, int-32 does not define any methods for manipulating its values (e.g., adding and subtracting). It is also agnostic on the semantic interpretation of its values ... it does not even signify whether the integer value should be interpreted as signed or unsigned. Its lack of built-in methods and interpretation is what makes it an ideal foundation for defining new types with very different interpretations and methods.
enum is used to declare a collection of symbols which are mapped to integer values.
enum PhoneType: Home, Work, Mobile
These symbols are automatically mapped to unsigned integer values: Home to 0, Work to 1, and Mobile to 2. Use of a name is qualified by its enum name: PhoneType::mobile.
It is possible to explicitly specify the bit-size and/or the numeric values the symbols map to:
enum Colors int-32: Red = 0xFF0000, Green = 0x00FF00, Blue = 0x0000FF
Even though the symbols map to integer values, they are not aliases of one of the defined integer types (e.g., u8). They have a distinctly named type (e.g., "Colors"). Even though the values are numbers, they have no pre-defined arithmetic methods attached to them. You cannot add, subtract, multiply or divide enumerated values.
An enum value may only be compared for equivalence (and not order).
Custom Number Types
There are several reasons why we might want to define distinctly different number types than those provided by the standard library:
- One might want to use different types to distinguish between units of measure, thereby potentially avoiding problems like the loss of the $125 million Mars probe.
- Different number types could make different promises for undefined behavior (e.g., protecting against undesired overflows), or could guarantee the number values are bounded by some range.
- Each named set of enumerated values can belong to its own independent type, and can prevent attempts to arithmetically manipulate an enumerated integer value.
- Integers that support intrinsic atomic operations can be separately typed.
Creating a new numeric integer type is nearly as simple as wrapping an primitive integer type as a field in a struct. For example:
struct Nbr32: nbr int-32
Methods may be added to this struct to define the operations that may be performed on values of this type. These methods can make use of fast internal integer primitive functions (TBD).
Although numbers of one type are never implicitly converted into the equivalent number of another type, it is always possible to explicitly request this conversion using a type constructor:
imm converted = Nbr32[somenbr]