Skip to main content

Next version

Planned for Kalem v1.1. The design of tasks, wait for, sending events and collections is settled; the rest is designed with that version. None of it is in the language yet.

Tasks and waiting​

/// The dough rises, bakes and goes to the window.
task bake(loaves: int)
bakery.stage = "rising"
wait 45m
bakery.stage = "baking"
wait 30m checkpoint baked
bakery.stage = "ready"
bakery.loaves += loaves
end

state Working
on enter
run bake(12) // scope state by default: cancelled when Working ends
end
end
  • Waiting happens only in a task body: wait <duration> and wait until <time> (the next time the clock reaches it). Functions a task calls cannot wait. Between two waits is one transaction.
  • run task(...) [scope state | scope script]. The default is scope state: the owner is the activation of the state when run ran, not where the code is written. scope script ties the task to the instance. When its owner ends, the task is cancelled in that transition's transaction; cancel task cancels it explicitly.
  • A task name runs at most once at a time; a second run of a running task is an error. A task starts from a first-in, first-out queue after the transaction that ran it is applied.
  • If a task makes a goto that ends its own owner (even indirectly), the transition is applied and the task ends there.
  • After a wait the world may have changed: one thread does not keep a decision made before the wait true, so a task checks again.
  • A waiting task is plain data: the task, where it goes on, its live locals with their types, its owner and when it wakes up. checkpoint name gives the resume point a lasting id; it is no promise against code changes.
  • In a migration a task goes on only if its code, the functions it calls and its resume shape are the same; otherwise it is cancelled and reported, and on migrate repairs the behaviour.

Also designed​

  • wait for <event> [timeout <duration>], with its rules for a missed event, delivery to all who wait, a tie with the timeout, cancelling and loading.
  • Sending events (send) and object references (ref<Type>), which need rules for the target's permission, for objects removed or unloaded, and for the queue's limit. engine events cannot be imitated. A weak reference alone is not a contract for an object's life.
  • Collections (list<T>, map<K, V>) and struct are values: they are copied on assignment (copy-on-write inside) and cannot hold cycles. Indexes start at 0; an index out of range or a missing key is an error, and get(key, fallback) looks up safely. A map is walked in insertion order, and an entry removed and added again moves to the end. A copy costs its budget per element. As properties they wait for the editor's forms to support them.

Later​

Overriding functions by state; memory and events on the client (the time since an input changed, a flicker when the power comes back); lifecycle events dispose (when a binding is removed, with its reason) and, on the client, viewEntered/viewExited; duration properties; trigonometry on the server.