Enums

Enums are types which may be one or a few different variants.

enum Number {
    Int: i32
    Float: f32
}

enum TokenTypes {
    String: str
    Integer: i32
    Number: Number
    Character: char
    Invalid
}

main {
    let str_token = TokenTypes::String("some token type");
    str_token == TokenTypes::String; // returns true

    // str_token gets automatically unwrapped
    if str_token == TokenTypes::String print(str_token) // prints "some token type"
    else if str_token == TokenTypes::Integer print(str_token + 5)

    let num_token = TokenTypess::Number(Numbers::Int(3000));
}

"Unwrapping" enums

By default all items are "wrapped" - their values and unknown and can be anything.

let char_token = TokenTypes::Char('a'); 
// Even if it's clear that char_token is of type `char`, Lazy doesn't allow you to use it. 

To use the value inside the variant you'll have to "unwrap" it.

if unwrapping

if let TokenTypes::Char(ch) = char_token {
    // You can use `char_token` as a character now.
    ch.to_string(); // "a"
}
// char_token is wrapped here.

if char_token == TokenTypes::Char('a') {
    // char_token is still wrapped, but you know it's value.
}

match unwrapping

match char_token {
    TokenTypes::Char(ch) => {
        print(ch);
        // char_token is unwrapped here
    },
    _ => {
        // char_token is wrapped, this portion only executes when nothing else got matched
    }
}

Attaching methods and properties to enums

Attaching methods and properties to enums is done via the impl keyword.

enum Option<T> {
    Some: T,
    None
}

type Unwrap<T> = {
    unwrap: () -> T,
    is_some: () -> bool,
    unwrap_or: (v: T) -> T
}

// The impl block's typings must match the structure's
impl<T> Unwrap<T> for Option<T> {
    unwrap: fn() -> T {
        match self {
            Option::Some(val) => val,
            Option::None => error("Tried to unwrap an empty option!")
        }
    }

    is_some: fn() -> bool {
        self == Option::Some;
    }

    unwrap_or: fn(v: T) -> T {
        match self {
            Option::Some(val) => val,
            Option::None => v
        }
    }
}

main {
    let maybe: Option<i32> = Option::None;
    maybe.unwrap_or(0); // 0
    maybe = Option::Some(32);
    maybe.is_some(); // true
    maybe.unwrap(); // 32
}