Skip to content


A type is an attribute of data which tells the compiler how the data will be used. The type also defines the operations that can be done on the data, the meaning of the data, and the way values of that type can be stored.

Primitive types

A primitive type is a type that is implemented at a language level. It does not require a library (even the standard one) to work. Also, a primitive type can't be extended. We can class the different primitive types using these simple rules:

  • The primitive type storing nothing is called “void”.
  • The primitive type storing a boolean is called a “bool”.
  • Primitive types storing an integer are called “integer types”.
  • Integer types storing a signed integer are called “signed integer types”.
  • Integer types storing an unsigned integer are called “unsigned integer types”.
  • Primitive types storing a float are called “floating point types” or just “float types”.

In Ergol it exists only the 13 following primitive types (grouped by category):

graph TD PT[primitive type] PT --> V([void]) PT --> B([bool]) PT --> I[integer type] I --> SI[signed integer type] SI --> I8([i8]) SI --> I16([i16]) SI --> I32([i32]) SI --> I64([i64]) I --> UI[unsigned integer type] UI --> U8([u8]) UI --> U16([u16]) UI --> U32([u32]) UI --> CHR([char]) UI --> U64([u64]) PT --> F[float type] F --> F32([f32]) F --> F64([f64])

Primitive types are further explained in the Primitive Types section.

Other types

graph TD A([any]) --> PT[primitive type] A --> TPL([tuple]) TPL --> TPLI([...]) A --> FN([fn]) FN --> FNI([...]) A --> TYP([type]) A --> O([object]) O --> STR([String]) O --> REG([Regex]) O --> ARR([Array]) O --> DIC([Dictionary]) O --> OI([...])

“any” type

As its name suggests, the “any” type refers to any type. An unsigned 8-bit integer is of type “u8”, but also of type “any”. A function is of type “fn”, but also of type “any”. Etc...

“tuple” type

The “tuple” type refers to any tuple. Every tuple have a type extending the “tuple” type.


let t = (1, 2, 3);

printl(typeof t);                  // tuple<i32, i32, i32>
printl(t is tuple<i32, i32, i32>); // true
printl(t is tuple);                // true

“fn” type

The “fn” type refers to any function type. Every function have a type extending the ”fn“ type.


// The "fn" bellow is just a keyword. It does not refer to the "fn" type.
fn even(i32 x) -> bool {
    return x %% 2 == 0;

printl(typeof even);              // (i32) -> bool
printl(even is ((i32) -> bool));  // true
printl(even is fn);               // true
printl(even is any);              // true
printl(even is i32);              // false

The type of a function “A” inherits from the type of a function “B”, if and only if, every possible calls on “A” are also possible on “B” and the return type of “A” inherits from the return type of “B”.


fn A(i32 x, i32 y) -> i32 {
    // stuff here

fn B(i32... x) -> i32 | bool {
    // stuff here

let res = A(42, 42); // This call is possible and will return a i32.
let res = B(42, 42); // This call is possible and will return a i32 | bool.

// Every call that can be made on A can also be made on B, also i32 inherits from i32 | bool.
// Therefore, A inherits from B.

let res = B(); // This call is possible and will return a i32 | bool.
let res = A(); // This call is not possible.

// B does not inherit from A.

// summary:
printl(A is (typeof B)); // true
printl(B is (typeof A)); // false

“type” type

The “type” type is the type of a type. For example, an 8-bit unsigned integer is of type “u8”, but u8 itself is of type “type”. This special type allows to have type at runtime.


i32 i = 3;

printl(typeof i);           // i32
printl(typeof i32);         // type
printl(typeof (typeof i));  // type
printl(typeof type);        // type

Example of user defined types:

type char_array = char[] | String;

char_array test_1 = char['f', 'o', 'o'];
char_array test_2 = "foo";

printl(typeof test_1);         // char[]
printl(typeof test_2);         // String
printl(typeof char_array)      // type

printl(test_1 is char_array);  // true
printl(test_2 is char_array);  // true
printl(test_1 is char[]);      // true
printl(test_2 is char[]);      // false
printl(test_1 is String);      // false
printl(test_2 is String);      // true

printl(char_array == (char[] | String));  // true
printl(char_array == (String | char[]));  // true

“object” type

The “object” type refers to the type of any object (class instance). The “String”, “Regex”, “Array” and “Dictionary” types are all “object” types. Also, they are a bit special because:

  • They have built-in language support.
  • They can't be inherited.
  • They can be instantiated with literals.
  • They can't be instantiated with the “new” keyword (except for “Regex”).

“void” type

The void type represents the absence of data. It's not represented on the chart because it doesn't exist at runtime.

Last update: June 16, 2021