Skip to content

Latest commit

 

History

History

toit

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Toit

CLI

  • toit
  • toit doctor - health check of local system
    • toit doctor fix - install or update the SDK
    • toit doctor -v - show version information
  • toit exec <file> - execute the program without a device

The toit SDK installation is placed in ~/.cache/toit

Variables

  • locals - a variable declared within a function or passed to a function
  • globals - a variable declared outside the scope of a class or function
  • constants - special case of globals defined by a ::= assignment. By convention constants should have an ALL_CAPS_NAME

Classes

  • Constructor
  • Named Constructor
  • Factory - a named constructor with a return
  • Static functions and fields - marked with the keyword static
  • Methods and instance fields

Basic Types

Types are optional. A variable is typed if followed by a /type-name. By default types are non-nullable, which means null is not a valid value.

class Coordinate:
  // An instance field that must be initialized by
  // constructors.
  // By writing `:= ?` we indicate that all constructors
  // must initialize the field.
  x /int := ?
  y /int := ?

  // We don't need to specify the type for constructor
  // arguments that are written directly to a typed field.
  constructor .x .y:

main:
  a := Coordinate 0 0

  // Error! The types of the fields (and therefore the
  // constructor arguments) are non-nullable, so null is not
  // a valid argument here:
  b := Coordinate null null  // Error!

Nullable types are defined using a ? after the type name.

class Foo:
  bar /Bar? := null
any/none - Two special types exists:
  • any - any value is accepted
  • none - no value is accepted

The return type is defined with -> type

// A function that doesn't return anything.
foo -> none:
  print "not returning anything"

// A function that takes an int and returns an int.
bar x/int -> int:
  return x + 1

See definition of operators on the classes for int, float and num

// simple function definition with 2 arguments, argumment 2 has a default value
some_fct argument1 argument2="default value":
  print "arguments: '$argument1' '$argument2'"

main:
  // showing calls to the 'some_fct' function
  some_fct "test 1"
  some_fct "test 1" "test 2"
// simple *class* definition
class SimpleAdder:
  addend1_ := null // private by convention as ending in '_'
  addend2_ := null // private by convention as ending in '_'

  // the constructor assigning addend1 and addend2, defaults to 0
  constructor .addend1_=0 .addend2_=0:

  sum:
    return addend1_ + addend2_

main:
  // creating an instance and calling 'sum'
  simple_adder := SimpleAdder 13 17
  print "the first sum is $simple_adder.sum"

  // creating an instance where addend2 is default value (0)
  simple_adder_noop := SimpleAdder 13
  print "the second sum is $simple_adder_noop.sum"

Toit also supports interfaces and abstract classes

The Advanced Constructor Topics details how an object is constructed and how the sequence is split into an initialization and an instance part.

// function with named argument
say_hi name --greeting="Hello ":
  // Greet everyone individually!
  print "$greeting $name"

main:
  // calling a function with a named argument
  say_hi "Peter"
  say_hi "Berit" --greeting="Hi"
// loop using number.`repeat`
print_n_numbers n:
  // using repeat on number
  n.repeat: print it // `it` is an *automatic* variable that gives the iteration count

  // traditional for loop
  for i := 0; i < n; i++: print i

  // traditional while
  i := 0
  while i < n: print i++


// define a list and loop over it, using the `do` method available on all collections
print_list:
  list := [ "Horse", "Fish", "Radish", "Baboon" ]
  list.do: print it // `it` is an *automatic* variable that gives the element
  print (list.join ",")


// if..else
print_even_or_odd n:
  if n % 2 == 0: print "$n is even"
  else: print "$n is odd"
list_of_something := []   // empty list
map_of_x_to_y     := {:}  // empty map
set_of_something  := {}   // empty set

Iterating a map iterates the key value pairs - see block arguments

main:
  map ::= {
    1234: "Siri",
    2345: "John",
    3456: "Sue"
    }
  map.do: | id name |
    print "$name has ID $id"

do and repeat looks like they are built in to the language like if and for, but they are normal methods on the List and Integer classes

class List:
  // ...
  do [block]:
    size.repeat: block.call this[it]

class Integer:
  // ...
  repeat [block]:
    for i := 0; i < this; i++:
      block.call i

As blocks are stack-allocated there are some restrictions on blocks.

Concurrency - tasks

Toit uses Cooperative scheduling where all tasks / fibers runs on the same heap and only switch task on yield points.

A task is started with task:: syntax (double :)

import gpio

// The red LED is connected to pin 17.
LED1 ::= gpio.Pin.out 17
// The green LED is connected to pin 18.
LED2 ::= gpio.Pin.out 18

main:
  // Note the double `::` on the next two lines.
  // Start a task that runs the my_task_1 function.
  task:: my_task_1
  // Start a second task that runs my_task_2.
  task:: my_task_2

my_task_1:
  while true:
    sleep --ms=500
    LED1.set 1
    sleep --ms=500
    LED1.set 0

my_task_2:
  while true:
    sleep --ms=123
    LED2.set 1
    sleep --ms=123
    LED2.set 0

Synchronization Methods

Synchronization between tasks is possible using the monitor library

  • latch
  • channel
  • semaphore
  • mutex
  • mailbox
  • try .. finally
  • catch - implemented as a function that takes the possibly throwing code as a block.
my_function:
  my_exception := catch --trace:
    code_that_might_throw 42 103
  if my_exception:
    code_to_run_when_an_exception_was_thrown "foo" "bar"

Hardware - ESP32

GPIO (General Purpose I/O)

GPIO pins are globally acquired

import gpio

main:
  pin := gpio.Pin 21  // Acquired system-wide.
  // ...
  pin.close           // Released, can be used by other applications now.

Two different modes:

Running apps on the Device

Two modes

  • run - run once
  • deploy - deploy with a .yaml app specification file

Simulator Device

toit simulator start --alias TestDevice  # start a simulator device named 'TestDevice'

toit run -d TestDevice hello.toit        # run the hello program once
toit deploy -d TestDevice hello.yaml     # deploy the hello app to the device

toit device -d TestDevice ps             # list apps on the device
toit device -d TestDevice logs -f 10m    # attach to the logs from 10 minutes ago and tail
toit simulator stop TestDevice           # stop the device

Asynchronous message communication between apps.

topic is a named resource which is used when messages are published.

  • Device topic: A topic that enables intra-communication on a device. These topics are prefixed with: device:
  • Cloud topic: A topic that enables inter-communication between devices and external systems. These topics are prefixed with: cloud: