Hi,
Ryan Joseph wrote 11 lines
> On Dec 19, 2018, at 5:23 PM, Sven Barth via fpc-pascal
> wrote:
>
> A library as first step would be more useful. Later on one can think
> about integrating it into the language itself.
>
How does that work? I’ve been interested in coroutines for a while now
but I don’t understand how they function in the language. They would
need to manage stack states and push/restore stacks, which is something
a library can’t do right?
(After reading that old thread we had...)
Actually, it can. The only thing you need to do is to allocate a stack first, then make the "coroutine" functions use it, which is basically boils down to how you pass your arguments and self instance to the coroutine on initializatin, while you change the stack pointer register, and then how you restore it in the end. It might be messy, with small bits in platform-specific assembly - actually the compiler or the RTL could indeed help a bit there, but this is not a requirement - but theoretically possible, on the other hand I have absolutely no clue from the top of my head how that would interfere with any sort of debug info generation, and/or exception handling.
Actually, if you check the Amiga startup code in the RTL, that already does this, as AmigaOS and similar systems have a single address space approach, with a limited size stack, so the RTL startup code checks if the stack is big enough, and allocates a new one if it is too limited for the application to run. The OS provides the necessary stack-swap functionality there, while storing the old stack values for reuse in a small structure, but this code could just as well be in the application, or your library in this case. Then the code utilizes setjmp/longjmp to restore register state on exit, before it quits and restores the old stack.
https://github.com/graemeg/freepascal/blob/master/rtl/morphos/si_prc.pp#L47
https://github.com/graemeg/freepascal/blob/master/rtl/amiga/m68k/si_prc.pp#L60
So to sum it up, after you set up a separate stack and stack pointer register to your coroutine, the previously discussed setjmp/longjmp method should work for switching between them.
(Also, if you set up some example-library framework, I might be able to help with getting the stackswap thing running, if you are not too comfortable with that. Even if I think this entire coroutine idea is just a too big of a can of worms to integrate into a compiler/language and a standard library, but as a separate library it might have its uses indeed.)
Cheers,
Charlie