Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Machines

A machine is the core abstraction in Lake. Every machine call spawns a new cooperatively-scheduled process.

Defining a Machine

name is {
  # branches
}

The is keyword separates the machine name from its body. The body is enclosed in curly braces and contains one or more branches.

A Simple Machine

A counter that recursively decrements until it reaches zero:

@rt(rt_write)

counter is {
  n i64 -> {
    when 0 == n {
      true  -> { rt_write(1 "done\n" 5) }
      false -> { self(n-1) }
    }
  }
}

main is {
  _ i64.0 -> {
    counter(5)
  }
}

When main calls counter(5), a new process is spawned running the counter machine. The self(n-1) call does not spawn a new process — it transitions the current process to a new state.

Concurrent Execution

Calling a machine always spawns a new process. Multiple spawns create concurrent processes managed by the cooperative scheduler:

@rt(rt_write)

worker is {
  steps i64 acc1 i64 acc2 i64 -> {
    when 1 <= steps {
      true  -> { self(steps-1 acc2 acc1+acc2) }
      false -> { rt_write(1 ".\n" 2) }
    }
  }
}

main is {
  _ i64.0 -> {
    worker(100000 0 1)
    worker(100000 0 1)
    worker(100000 0 1)
    worker(100000 0 1)
  }
}

Here main spawns four worker processes. They execute concurrently — each process runs a quantum of work (256 blocks) before yielding to the scheduler.

Ping-Pong Example

Machines can spawn each other:

@rt(rt_write)

pong is {
  _ i64.0 -> {
    rt_write(1 "pong\n" 5)
  }
}

ping is {
  _ i64.0 -> {
    rt_write(1 "ping\n" 5)
    pong()
  }
}

main is {
  _ i64.0 -> {
    ping()
    ping()
    ping()
  }
}

main spawns three ping processes. Each ping prints “ping” and then spawns a pong process that prints “pong”.

Declaration Order

Machines can be declared in any order. Forward references work:

main is {
  _ i64.0 -> {
    worker(10)
  }
}

worker is {
  n i64 -> {
    when 0 == n {
      true  -> { rt_write(1 "done\n" 5) }
      false -> { self(n-1) }
    }
  }
}