Data - Types and Kinds

Datatypes

Number

String

Kind

Boolean

Kind

Atom

Kind

Kind

Kind

Empty

Kind

Examples

Data Structures

Kinds

Syntax

Kind Annotations

Simple Kinds

Compound Kinds

Custom Kinds

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 integer

        • i16 - 16-bit signed integer

        • i32 - 32-bit signed integer

        • i64 - 64-bit signed integer

        • i128 - 128-bit signed integer

      • Unsigned - Can only represent zero and positive values.

        • u8 - 8-bit unsigned integer

        • u16 - 16-bit unsigned integer

        • u32 - 32-bit unsigned integer

        • u64 - 64-bit unsigned integer

        • u128 - 128-bit unsigned integer

    • Fractional - Decimal numbers with fractional components.

      • f32 - 32-bit floating-point number

      • f64 - 64-bit floating-point number

    • Rational - Represents rational numbers as a fraction of two integers.

      • r64 - 64-bit rational number (with numerator and denominator as a pair of i64)

  • Imaginary - Represent imaginary components of complex numbers.

    • c64 - 64-bit complex number (with real and imaginary parts as a pair of f64)

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

<[u8]>--

A matrix of unsigned 8-bit integers

<(o,O)>--

A tuple of two elements of kind o and O respectively

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:=[
1
2
3
]
--

1x3 row vec of f64 numbers: [f64]:1,3

y<[u8]>:=[
4
5
6
]
--

1x3 row vec of u8 numbers: [u8]:1,3

z<[u8]>:=x--

Convert [f64]:1,3 to [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

[T]:N,M

<[u8]:2,3>

Set

{T}:N

<{u8}:3>

Record

{T1,T2,..}

<{x<u8>,y<string>}>

Map

{K:V}

<{string:i32}>

Table

|arg1,arg2,..|:N

<|x<u8>,y<string>|:3>

Tuple

(T1,T2,...)

<(u8,string,bool)>

Enum

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>:=[
1
2
3
]
--

Defines v1, a 3-element vector of f32 values

v2<point3>:=[
4
5
]
--

Error: kind mismatch, expected 3 elements but got 2