Skip to content
Benjamin Dupont edited this page Aug 15, 2020 · 3 revisions

Unions

A union accepts multiple types.

type Resource = Employee | Machine | ThirdParty

Intersections

An intersection accepts values that are of all specified types at the same type.

type Loggable = Into<str> & Entity.Timestamped

Structs

A struct can be defined using the struct {} type constructor.

type Employee = struct {
    // struct body
}

Fields

Structs are composed solely of fields, defined with the <name>: <type> syntax and separated by commas.

type Employee = struct {
    name: str, dept: i32
}

Construction

Structs can be constructed using the initializer syntax:

let a = Employee(name: "Jenna", dept: 12)

Classes

A class can be defined using the class {} type constructor.

type Request = class {
    // class body
}

Properties

Class properties are defined thourghout the class, using the property keyword.

type Request = class {
    property body: str
    property uid: i32
}

Methods

Class methods are defined inside the class body.

type Request = class {
    property body: str
    property uid: i32

    function describe() {
        print("I am a request with UID " + uid + ", and contain \"" + body "\" in my body.")
    }
}

Free functions inside classes are not allowed.

Construction

Cyan does not have explicit class constructors. To instantiate a class, use the initializer syntax.

let a = Request(body: "Ping", uid: 4)

Default values

Default values are supported.

type Request = class {
    property body: str
    property uid: i32 = 5

    function describe() {
        print("I am a request with UID " + uid + ", and contain \"" + body "\" in my body.")
    }
}
let a = Request(body: "Ping")

print(a.uid) // 5

Derived properties

It is possible to always derive a property from a property with a specified value with the implicit keyword.

Implicit properties cannot be specified in initializers.

type Request = class {
    property body: str
    property uid: i32 = 5

    implicit repr = "Body: $body, UID: $uid"
}

Calculated derived properties

A derived property can be computed on each access with the => assignment operator.

type Request = class {
    property body: str
    property uid: i32 = 5

    implicit repr => "Body: $body, UID: $uid (rand. value: ${random<i32>(15, 25)})"
}

Traits

Traits allow specifying behaviors that can be composed into classes.

type Printable = trait {
    function print(): void
}

A class can derive a trait (implement its behavior) with the derive keyword.

type Request = class {
    property body: str
    property uid: i32 = 5

    derive Printable {
        print() {
            printf(repr)
        }
    }

    implicit repr => "Body: $body, UID: $uid (rand. value: ${random<i32>(15, 25)})"
}

Trait properties

Traits can be composed of both functions and properties.

type Printable = trait {
    repr: str

    function print(): void {
        printf(repr)
    }
}
type Request = class {
    property body: str
    property uid: i32 = 5

    derive Printable {
        implicit repr => "Body: $body, UID: $uid (rand. value: ${random<i32>(15, 25)})"
    }
}

Delegated trait implementations

Trait implementations can be delegated to specified or implicit properties that implement that trait.

type Call = class {
    property req: Request

    derive Printable by req
}

A trait with a single property can be implemented by delegation to a class property with the same type.

type Id = trait {
    id: any
}
type Request = class {
    property body: str
    property uid: i32 = 5

    derive Id by uid
}