I'm sick of doing doco stuff so I need a break for a while. So here's what I'm thinking:
1. Create a type for labels. So you can do this: var lab : label; here:>> code_stuf; lab = here; // label assignment stuff; goto *lab; // computed goto Felix already does this in the C++ code. For gcc (and clang) we use a void * as the label type and a gcc extension computed goto which is literally as written above: goto *lab. If there's no support, we just use an integer, the label gets replaced by case 42: and lab becomes an int variable and the assignment is lab = 42; To make this one work we change the goto to say: pc = lab; goto start; and start says: switch (pc) { ... case 42: ... } All this works right now, its how Felix procedures work. Macros choose which implementation (the compiler doesn't know). Long jumps also try to use "assembler labels" which is also gcc hackery. Yes, I know gotos are bad and computed gotos are really bad. Only, no, they're not, they're completely fundamental basics :) 2. Now I will add a new instruction: BEXE_exchange (ptarget, psave) ptarget and psave are expressions which point to label variables. The instruction fetches ptarget, store the return address at psave, sets the program counter to the fetched target, and returns to the driver. The driver then executes the procedure's resume() which causes the target to run. So this instruction is precisely a goto, except the old location is also saved so we can jump back later. We could also just do an ordinary goto (with a computed target). This all assumes the jump is into the current procedure. It allows you to zig-zag around the code. 3. To handle foreign procedures, we do the same, except now we have to return the "this" pointer of the foreign procedure, and set the PC of that procedure instead of the current one. NOTES ====== The reason for doing this is to natively support coroutines directly in the Felix code. This does not solve the original problem, which is how to *inline a generator*. However it does provide the tools required to do that, so the compiler can later be modified to do the inlining using the same mechanism the user would write. It's likely this generalisation of the *existing* technology will have major benefits. In particular the execution model may well get modified. At present each procedure has a PC variable, so the pair this, PC is the program counter. There is also another variable return_address which is the this pointer of the caller. The PC inside the caller is stored in the caller. So its not re-entrant. Although this could be split out, there are two problems: it requires an extra heap allocation, and, the benefits of "restartable" continuations are limited to functional continuations because functional code cannot modify anything. In procedural code, the state data gets modified so "restarting" a procedure will always get "whatever the current variables hold". So restarting "from the top" is meaningless. This is why Felix actually clones functions (to get freshly initialised local variables), and explains what a generator is: a function that *doesn't* clone its prototype. So I don't see much benefit in splitting the program counter out of the data frame at the moment. Actually I see more benefit in splitting some data out of the frame. In other words, when you return a closure, instead of just a pointer into the parent context frame to get at variables, use pointers to the variables. Now we can happily copy the pointer up, and get rid of the pointer to the parent frame. The benefit is that when we do a long jump we don't have to "unwind the stack". We have to do that now to breaks cycles, otherwise a pointer to a deeply nested frame will cause the whole call chain to be reachable, so Felix NULL's out the return addresses to break the cycles. This problem would "go away" entirely if the control object *contained* a pointer to the data frame, instead of being embedded in it. -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ WatchGuard Dimension instantly turns raw network data into actionable security intelligence. It gives you real-time visual feedback on key security issues and trends. Skip the complicated setup - simply import a virtual appliance and go from zero to informed in seconds. http://pubads.g.doubleclick.net/gampad/clk?id=123612991&iu=/4140/ostg.clktrk _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language