Continuations are a generalization of control constructs: from a common primitive, you can build such things as loops (with exits), exceptions,
and even coroutines.
The way I have implemented this in GXScript is with the “cexec” operator: this takes a procedure as an argument, like “exec”, but before calling it, it pushes a continuation object on the stack. Invoking this object will transfer control to the point immediately following the cexec call that
created it.
Example:
{
/Count 5 ldef
/Top null ldef
{/Top exch lstore} cexec
{
/Break exch ldef
Count =
/Count Count 1 sub lstore
Count 0 eq {Break} if
Top
}
cexec
}
exec
Output:
5
4
3
2
1
But that’s a clunky way to have to write a loop every time. So why not package up the creation of the continuations in a reusable procedure:
/DoLoop
{
/Proc exch ldef
/Top null ldef
{/Top exch lstore} cexec
{Proc Top} cexec
}
ddef
DoLoop will take your loop-body procedure as argument, and execute it repeatedly, each time pushing a continuation that can be used to exit the
loop, until you invoke that continuation. Example use:
/Count 5 ddef
{
/Break exch ldef # always pop arg even if not used
Count =
/Count Count 1 sub lstore
Count 0 eq {Break} if
}
DoLoop
The output is the same as before.
The source is here <
https://bitbucket.org/ldo17/gxscript/> if you want to
have a play.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)