That was easily fixed by being sure to clone the parameter and return variable information immediately prior to invoking the function. In other words, we went from having a shared stack frame descriptor for every function invocation, to having a unique descriptor copy for each invocation.
It's a tiny bit of overhead on every function call, but Fugue was never meant to be performant - just a reference implementation of the higher-level points of the language. So I don't really care [grin]
The upshot is that, for the first time in Epoch history, this code is valid and will function perfectly:
entrypoint : () -> (){ recurse(3)}recurse : (integer(counter)) -> (){ debugwritestring("n Bottles of Beer on the wall... where n is:") debugwritestring(cast(string, counter)) if(notequal(counter, 0)) { recurse(subtract(counter, 1)) } }
Epoch doesn't yet detect tail recursion, so even this simple little program can smash the stack if the recursion depth is set too high. I'll have to do some serious studying up to learn how to deal intelligently with tail recursion; probably something that'll come way down the road, once more heavy-duty features are in place.
Depending on how long it takes me to finish the documentation and cleanup process, we should be seeing Release 3 in the next couple of days. Woohoo!
Ninja Update - 1936 hours
I only have 21 files left (out of 62) to document. If I stay as bored over the next hour as I did over the last, I should be able to get R3 out tonight.
More Ninja-Action - 2009 hours
Down to 10 files, but most of them are comparatively large. I've left them for last because I am lazy and worthless. R3 is still on track for later tonight... hopefully.
Speaking of files, I need to go through and clean everything up. I'm not a big fan of sticking every little helper class into its own file, but Tangent's getting a little attic-y for even me. 8 files for the language, 6 for the parser framework. [depressed]
Yes, definitely re-org time.