Connect IQ SDK

Introduction to Monkey C

Monkey C is an OO language that works with the Monkey Brains virtual machine designed for easy app development on wearable devices. The goal of Monkey C is to round the sharp edges of making a wearable app, letting you focus on the customer and less on resource constraints. Monkey C is an object-oriented language from the ground up. It uses reference counting to automatically clean up memory, freeing you from focusing on memory management. The resource compiler helps you manage different screen layouts between different devices.

The Monkey Brains VM runs on top of our RTOS, and exposes APIs for graphics, page layouts, location, activity tracking, persistent storage, and communication with mobile devices and sensors. The goal is to extend our devices onto the wearable web by allowing you to bring rich connected content to the Connect IQ platform.

The Tao of the Monkey

There is a rhyme and reason behind Monkey C to make it easy for you to support our ecosystem of products.

Hello Monkey C

There is no better way to learn Monkey C than by jumping right in. Let’s take a look at the application object of a watch face.

using Toybox.Application as App;
using Toybox.System;

class MyProjectApp extends App.AppBase {

    //! onStart() is called on application start up
    function onStart() {
    }

    //! onStop() is called when your application is exiting
    function onStop() {
    }

    //! Return the initial view of your application here
   function getInitialView() {
    return [ new MyProjectView() ];
  }
}

If this looks familiar and non-threatening, that’s the point. Monkey C is intended to be the language you didn’t know you already knew.

At the top is a using statement, which is analogous to C++’s using statement, or an import in Java™, Ruby, or Python™. Using statements lexically bring modules into our name space. After a using clause, we can refer to a module by its shortened name (in this case System). Toybox is the root module for Monkey C system modules; all the cool toys are kept in there.

To print out values to the debug console, use:

System.println("Hello Monkey C!");

System is the Toybox.System module we imported with the using statement. Unlike Java namespaces, Modules are static objects that can contain functions, classes, and variables. The println function should be familiar to Java programmers — it prints a string and automatically adds a new line. The system module has a number of useful functions:

//! Use println() to print to the console with a line terminator.
//! @param a Object or string to display
function println(a)
{
    print(a.toString() + "\n");
}

//! Use print() to print to the console
//! @param x Object or string to display
function print(x);

//! Use getTimer() to get the current millisecond timer.
//! @return [Number] System millisecond timer
function getTimer();

//! Get the current clock time with getClockTime().
//! @return [System.ClockTime] Current clock time
function getClockTime();

//! Get the current system stats with getSystemStats().
//! @return [System.Stats] Current system stats
function getSystemStats();

//! In future versions of the SDK trap() will break
//! into the debugger.
function trap();

//! To end execution of the current system with an error message
//! of "User terminated", call exit().
function exit();

//! Call error() to cause an error. This will exit the system.
//! @param [String] msg Error message to output
function error(msg);

Differences from Other Languages

As Italian and Spanish derive from Latin, Monkey C derives heavily from past languages. C, Java, JavaScript, Python, Lua, Ruby, and PHP all influenced the design for Monkey C. If you are familiar with any of those languages, Monkey C should be easy to pick up.

Java

Like Java, Monkey C compiles into byte code that is interpreted by a virtual machine. Also like Java, all objects are allocated on the heap, and the virtual machine cleans up memory (Java through garbage collection, Monkey C through reference counting). Unlike Java, Monkey C does not have primitive types; integers and floats are objects. This means primitives can have methods just like other objects.

Java is a statically typed language. The developer must declare the types for all parameters of a function, and declare the return value type. The compiler checks these at compile time to ensure type safety. Monkey C is duck-typed. Duck typing is the concept that if it walks like a duck, and quacks like a duck, then it must be a duck¹.

function add(a, b)
{
  return a + b;
}

function main()
{
  var a = add(1, 3); // Returns 4
  var b = add("Hello ", "World"); // Returns "Hello World"
}

The Monkey C compiler does not verify type safety, and instead causes a runtime error if a function mishandles a method.

Monkey C modules serve a similar purpose as Java packages, but unlike packages, modules can contain variables and functions. It is common for static methods to exist in the module as opposed to a particular class.

Lua/JavaScript

The main difference between JavaScript or Lua and Monkey C is that functions in Monkey C are not first class. In JavaScript, you can often pass a function to handle a callback.

function wakeMeUpBeforeYouGoGo() {
  // Handle completion
}

// Do a long running thing, and pass callback to call when done.
doLongRunningTask( wakeMeUpBeforeYouGoGo );

In Lua, to create an object, you bind functions to a hash table:

function doSomethingFunction(me) {
  // Do something here
}

// Constructor for MyObject
function newMyObject()
{
  local result = {};
  result["doSomething"] = doSomethingFunction;
}

Neither of these techniques works in Monkey C, because functions are bound to the object they are created in.

If you want to create a callback, you can create a Method object. Method objects are a combination of the function and the object instance or module they originate from. You can then call the method using the invoke method.

// Handle completion of long
function wakeMeUpBeforeYouGoGo() {
  // Do something here
}

// Create a call back with the method method (jinx!)
doLongRunningTask(method(:wakeMeUpBeforeYouGoGo));

Ruby/Python/PHP

Objects in Ruby/Python are hash tables, and have many of the properties of hash tables. Functions and variables can be added to objects at run time.

Monkey C objects are compiled and cannot be modified at runtime. All variables have to be declared before they can be used, either in the local function, the class instance, or in the parent module.

When importing a module, all classes inside the module have to be referenced through their parent module. You import modules, not classes, into your namespace.

¹This is different than Monkey Typing, where a thousand monkeys over infinite time write the works of Shakespeare.