Island & Cocoa

Right now, the Elements compiler provides two different modes that target the Apple platform, the new Island/Darwin back-end and the more currently default Toffee back-end.

The long term goal is to merge these two modes, and have the Island/Darwin platform mode be able to completely take over support for Cocoa, deprecating the separate "Toffee" toolchain.

Differences between Island/Darwin and Toffee

Both platforms compile CPU-native code for Apple's platforms, including macOS, iOS, tvOS and watchOS, using the LLVM compiler back-end, and tools from Apple's tool chain for secondary build tasks (such as processing storyboards).

Both platforms allow you to create any kind of project, from a simple class library to a full-fledged .app bundle for Mac or iOD devices.

The main difference is the core object model. The traditional "Toffee" tool chain for Cocoa is built completely on top of the Objective-C runtime, with its benefits and limitations. All classes defined in a Toffee project are, essentially, native Objective-C Runtime classes, and all external class-based APIs that apps interact (such as Foundation, AppKit or UIKit) with are Objective-C classes.

By contrast, the "Island" platform provides its own object model defined by Elements itself, and feature-compatible between all the Island sub-platforms. It is independent of the Objective-C runtime, and uses Island RTL and optionally Elements RTL as class library.

Object Models

On the Darwin sub-platform, the Elements compiler now provides support for separate class hierarchies, or Object Models, allowing access to both the Island-native classes and Cocoa APIs.

The two form two entirely separate class and type hierarchies, based on Foundation.NSObject and System.Object respectively. But the two class hierarchies can interact seamlessly, and objects from one hierarchy can be bridged to or wrapper up for use with the other. For example, you can store Island objects is a Cocoa NSArray class, or pass a Cocoa NSString to an Island API that expects a native String.

This is handled automatically by the compiler. Where compatible classes exist, they can be bridged or seamlessly cast between their corresponding types (in some cases toll-free). And classes specific to one object model can be automatically wrapped and unwrapped when passed to more generic APIs of the other model.

Interfaces can be declared, implemented on classes of both types, and be used to seamlessly work with objects regardless of which class hierarchy they live in.

By default, as on all Island platforms, when a new class type is declared without an ancestor it will become part of the Island-native class library, and descend directly from System.Object.

When an ancestor class type is provided as part of a class declaration, it will determine what class hierarchy the type will live in. Classes descendent from System.Object will be Island classes, and classes descendant from NSObject (or any of its sub-classes) will become part of the Objective-C (Cocoa) class hierarchy.

The [Island] or [Cocoa] aspects can also be used to explicitly mark a class as being part of the respective class hierarchy, when not providing an ancestor.

Default Object Model

For easy compatibility with the legacy Toffee platform, a new "Default Object Model" project setting is provided, and defaults to "Island". When set to "Cocoa" instead, classes will become part of the Cocoa class hierarchy by default.

In "Cocoa" mode, projects should behave pretty much 100% compatible with the legacy "Toffee" platform.