View on GitHub


A toy programming language.


The type system in toy is opt-in, but allows a lot of robust checks at runtime when needed. Types themselves are first-class citizens. To retreive the type of an existing variable, use the typeof keyword.

print typeof value;

The types available are:

Type Signature Description
null null Represents a lack of any meaningful value
boolean bool Either true or false
integer int Any whole number. The limits are implementation dependent
float float Any floating point number. The limits are implementation dependent
string string A series of characters, forming text
array n/a A series of values arranged sequentially in memory, indexable with an integer
dictionary n/a A series of key-value pairs stored in a hash-table, indexable with the keys
function fn A chunk of reusable code, which can potentially return a value of some kind
type type The type of types
opaque opaque Arbitrary data passed from the host, which Toy can’t natively understand
any any Can hold any value

Specifying Types For Variables

To specify a type for a variable, use : followed by the signature. In this example, the variable total can only ever hold integers (or null):

var total: int = 0;

To specify the type of an array or dictionary, use some variation of these signatures:

var array: [int] = [1, 2, 3]; //an array of integers

var dictionary: [string : int] = ["key":42]; //a dictionary of key-value pairs

Complex, hard-to-write types can be stored in variables, like so:

//define a variable called "entry"
var entry: type = astype [string: [string]];

//define a phonebook which follows the above signature
var phonebook: entry = [
    "Lucy": ["1234", "Cabbage Ln"],
    "Bob": ["5678", "Candy Rd"]


Const-ness, or the ability to fix the value of a variable, is part of the type system. To define a constant, follow the type signature with the const keyword:

var ANSWER: int const = 42; //answer will never change

You can also set the members of an array or dicitonary as const, or the entire compound:

var members: [int const] = [1, 2, 3]; //1, 2 and 3 cannot be changed, but "members" can be modified or re-assigned

var everything: [int] const = [4, 5, 6]; //everything is now const


Due to the syntax of Toy, when storing a complex type into a varable, you may need to use the astype keyword to differentiate the value from an array or dictionary.

var t: type = astype [int]; //t is a type, representing an array of integers
var u: type = [int]; //Error! it tried to assign an array with the sole entry "int"

First-Class Citizens

Types are first-class citizens. What this means is that they can be used just like any other value, as well as being stored in variables, and even returned from functions.

fn decide(question) {
    if (question) {
        return int;
    else {
        return float;

var t = decide(true);

var number: t = 0; //what if it had been false?

Opaque Data

Sometimes, you may need to pass data through Toy that Toy can’t normally handle. This data is called “opaque” data, and is passed around by reference rather than value. Anything can be passed in as opaque data, as long as it’s represented as a void pointer in C.

Toy_Literal opaque = TOY_TO_OPAQUE_LITERAL(&data, 0);


void* dataPtr = TOY_AS_OPAQUE(opaque);

int tag = TOY_GET_OPAQUE_TAG(opaque); //for identifying the data in the host

Managing and cleaning up opaque data is a task left entirely to the host program - you can do this with the opaque literal’s tag.