Data - Types and Kinds
Mech supports various primitive data types, each associated with one or more kinds. For example, the number 42 can be represented by an i32 datatype, which is of kind i32, signed, integer, real, number, and value (the latter of which is a sort of superset of all kinds).
Data types can be combined to form more complex structures, such as matrices, maps, sets, tuples, records, and tables. Each of these structures can also have associated kinds that are derived from the kinds of their constituent elements.
Datatypes
Data in Mech is represented using one of the following primitive datatypes:
Number
Number - Represents numeric values, including integers, floating-point numbers, and complex numbers.
Real - Real numbers, including integers and floats.
Integers - Whole numbers, which can be positive, negative, or zero.
Signed - Can represent both negative and positive values.
i8- 8-bit signed integeri16- 16-bit signed integeri32- 32-bit signed integeri64- 64-bit signed integeri128- 128-bit signed integerUnsigned - Can only represent zero and positive values.
u8- 8-bit unsigned integeru16- 16-bit unsigned integeru32- 32-bit unsigned integeru64- 64-bit unsigned integeru128- 128-bit unsigned integerFractional - Decimal numbers with fractional components.
f32- 32-bit floating-point numberf64- 64-bit floating-point numberRational - Represents rational numbers as a fraction of two integers.
r64- 64-bit rational number (with numerator and denominator as a pair ofi64)Imaginary - Represent imaginary components of complex numbers.
c64- 64-bit complex number (with real and imaginary parts as a pair off64)
String
A sequence of UTF-8 characters representing text.
Kind
<string>Boolean
Represents logical truth values.
Kind
<bool>Atom
A symbolic constant, often used for tags or enums.
Kind
The kind of an atom is itself. For example, the atom `A has the kind:
<`A>Kind
Represents a type or category of values, such as i32, f64, string, etc. Kinds can be used to classify values and determine their operations.
Kind
The kind of a kind is itself, and kind. For example, the kind <i32> has the kind:
<i32><kind>
Empty
Represents an empty value, placeholder, or the absence of a value.
Kind
<_>Examples
Data Structures
Enum - defines a set of named constant values
Map - stores key-value pairs for fast lookups.
Matrix - 2D array of homogenous values arranged in rows and columns.
Record - groups related fields, usually for representing structured data.
Set - unordered collection of unique values
Table - collection of heterogeneous data organized into rows and columns.
Tuple - fixed-size, ordered grouping of heterogeneous values.
Kinds
Every value in Mech has one or more associated kinds, which describe its type and properties.
Syntax
Any valid identifier can be used as a kind as long as it is unique in the program. Mech provides a set of predefined kinds for common data types, but you can also define your own kinds as well, and construct compound kinds from other kinds.
For example, the kind of a signed 32-bit integer is represented as: u8. The kind of a matrix is represented at [T]. These can be combined into the kind [u8], which represents a matrix of unsigned 8-bit integers.
Kind Annotations
Kind annotations are a tag that you can apply to values and expressions to specify their type explicitly. Syntatically they are specified with a form called a "kirby", which encases the kind in angle brackets:
<u8>--A value of kind
<[u8]>--u8A matrix of unsigned 8-bit integers
<(o,O)>--A tuple of two elements of kind
oandOrespectively
Kind annotations can be used to annotate literals with their data type:
x:=42<u8>-- defines x as an unsigned 8-bit integer with the value 42
They can be used for type conversions as well:
x:=[123]--1x3 row vec of f64 numbers:
y<[u8]>:=[[f64]:1,3456]--1x3 row vec of u8 numbers:
z<[u8]>:=x--[u8]:1,3Convert
[f64]:1,3to[u8]:1,3
Kind annotations can also be assigned to variables:
x:=<u8>-- Assigns the kind u8 as the value of x
The kind of x is its value, <[u8]>.
Simple Kinds
Kinds start from one of the primitive data types:
Data Type | Kind |
|---|---|
Signed integers | <i8>, <i16>, <i32>, <i64>, <i128> |
Unsigned integers | <u8>, <u16>, <u32>, <u64>, <u128> |
Floating-point | <f32>, <f64> |
Rational | <r64> |
Complex | <c64> |
String | <string> |
Boolean | <bool> |
Atom | <atom> |
Kind | <kind> |
Empty | <_> |
Compound Kinds
Kinds compose into more complex kinds based on the data structures they represent.
Data Structure | Kind | Example |
|---|---|---|
Matrix |
| <[u8]:2,3> |
Set |
| <{u8}:3> |
Record |
| <{x<u8>,y<string>}> |
Map |
| <{string:i32}> |
Table |
| <|x<u8>,y<string>|:3> |
Tuple |
| <(u8,string,bool)> |
Enum |
| <enum> |
Custom Kinds
You can define a custom kind with the following syntax:
<T>:=<S>-- Defines custom kind T, an alias for S
For example, if you wanted to represent a 3D point as a vector of three f32 values, you could define a custom kind like this:
<point3>:=<[f32]:3>Then you could use this kind to define a variable:
v1<point3>:=[123]--Defines v1, a 3-element vector of f32 values
v2<point3>:=[45]--Error: kind mismatch, expected 3 elements but got 2