Overview
A pecan.Co.co(...)
(or any of the syntax shorthands) will perform the following steps:
- If the expression was a function, remember the arguments and continue with the body of the function.
- Check the I/O types and normalise them.
- Types are normalised with
resolveType
, followed bytoComplexType
.
- Types are normalised with
- Define the instance type of the coroutine.
- This type must be defined quite early so that the coroutine can access its own instance when typing the body expression.
- Type a function of the form
function(reserved..., args...) { body; }
.reserved...
arepecan
-reserved identifiers, such assuspend
oraccept
. These must be in context for thebody
to type properly.
- Canonise the typed AST.
- This step converts expressions into a larger number of simpler expressions and many temporary variables. This allows the analysis performed in the next step to be simpler. For example, any
accept()
call will end up in its own "statement" or in asomevar = accept()
assignment.
- This step converts expressions into a larger number of simpler expressions and many temporary variables. This allows the analysis performed in the next step to be simpler. For example, any
- Convert the AST into a graph by performing control flow analysis.
- Embed the graph back into the untyped AST as a state machine.
- The embedding is a closure that first defines variables that are used from multiple CFG states, then defines the behaviour of
accept
,yield
and the coroutine itself as a set of functions, each of which is approximately in the formwhile (validState) currentState = (switch (currentState) { ... })
. The cases of theswitch
correspond to CFG nodes.
- The embedding is a closure that first defines variables that are used from multiple CFG states, then defines the behaviour of
- Define the factory type of the coroutine.
- Return an expression of the form
new Factory((co, args...) -> { ... })
.- The embedded graph is the closure given as a parameter to the factory. This allows closure semantics, i.e. the coroutine can access variables defined outside its own body.