spool-lang / Spool-Legacy-Repo

Legacy repo for the Spool programming language.
3 stars 0 forks source link

Traits and Definitions #2

Closed RedstoneParadox closed 5 years ago

RedstoneParadox commented 5 years ago

Traits are declared using the trait keyword and can be added to classes using the has keyword.

trait Foo {

}

class Bar has Foo {

}

Traits can also have default functions and non-default functions. Default functions have a body and can be overriden with the override keyword while non-default functions don't have a body and need to be overriden:

trait Foo {

    func doFooThing() {
        println("This has the trait Foo.")
    }

    func doOtherThing();
}

class Bar has Foo {

    override func doOtherThing() {
        println("This is a non-default function.")
    }
}

In an OOP language that relies on traits instead of inheritence, it becomes hard to define something based on traits; for example, if you have traits called Fur, Claws, and Motor; you know that a Mammal has Fur, can have Claws, but shouldn't have an Engine, but there is no way to express this in a purely trait-driven system. To allieviate this, Silicon has definitions, which are declared with the 'definition' keyword describe a type in terms of the traits it does have using the 'musthave' keyword, the traits it can have using the canhave keyword, and the traits it should not have using the hasno keyword like so:

definition Mammal {
has Fur
canhave Claws
hasno Motor
}

Alternatively, the nothingelse keyword excludes any traits not listed in the definition, so this would also exlude Motor and everything else:

definition Mammal {
has Fur,
canhave Claws,
nothingelse,
}

(The definition Any will be included with the standard library which doesn't require any traits, thus all classes fall under its definition.)

Definitions can then be used in generic parameters and boolean checks like so:

class Cat has Fur, Claws {

}

class Iguana has Claws {

}

class Furbey has Fur, Motor {

}

class Foo {

    main {

        typeCheck(new Cat())
        typeCheck(new Iguana())
        typeCheck(new Furbey())
    }

    func typeCheck(any : Any) {

        if (any is Animal) {
            announceAnimal<Animal>(any);
        }
    }

    func announceAnimal<T : Animal>(animal : T) { 
        println("An animal has arrived!")
    }
}

This would print An animal has arrived! when Cat gets passed in but not when Iguana or Furbey is passed in.

RedstoneParadox commented 5 years ago

This is being separated into two distinct issues.