Is it possible to leave a function more times than entering it?
Apparently:
ShowTraceLog
20 0 do
@renderBox
loop
:renderBox
"in" Trace
6 0 do
6 0 do
"out" I J Trace3
return
loop
"hello" Trace
loop
"bye" Trace
I wouldn't think of a function as more than a block of executed script in CRPL. In essence that's all they really are so you aren't really "leaving" anything so much more as you are 'injecting' code into a single statement of @MyFunction.
What do you mean by 'leaving' and 'entering'?
If you mean you're getting "out" more than you're getting "in" traced that's probably because "out" is in the loop.
Pay close attention to that loop. It only gets executed once before hitting a return statement.
What you are referring to is inlining, and inlining is not supposed to have any effect on the behaviour of control structures.
Looks to me like it's the convergence of calling a function in a loop, and returning from that function in a loop. The loop call in the main script is triggering the next cycle of the inner loop inside the function. The whole thing is stack based, so even though you're returning out of a function in the script, it still has 3 active nested loops going (because you haven't broken out of or ended them), and the loop statement iterates over the innermost one.
All three loops are necessary for the anomalous behaviour. Lose any one, and everything works as expected.
No you're right, I retract my statement after doing some poking around. :P
One detail I'm not too sure about is whether K extends beyond functions, since according to the stack (at least I'd assume) the outermost loop (according to wiki (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:k)) is still that one. And it always shows 0, there's no break statement in the first loop so it's baffling why it works like that. None of the loops are functioning at this point. Could you point out my mistake? I used Trace4 and added K after I J, always 0.
I cannot because I have not tested loop access between functions.
I would think at this point, you shouldn't expect a "bug fix" but should work on writing code that doesn't hit this bug. Can you provide an actual example where returning from a loop in a function is actually useful? Maybe we can help steer the code in a direction that doesn't hit this issue.
I have already fixed the issue with a workaround in my own code.
Here it is is in situ:
:renderBox
FALSE ->forcereturn
#render six by six square
6 <-y1 do
<-forcereturn if return endif
I ->y1
<-y0 <-y1 add dup ->y MapHeight gte if break endif
6 <-x1 do
I ->x1
<-x0 <-x1 add dup ->x MapWidth gte if break endif
#Watch the maximum time spent calculating
<-load 10000 gt if TRUE ->forcereturn return endif
@renderPoint ->terr
<-map <-x <-y MapWidth mul add <-terr SetListElement
@updateMap
loop
0 ->x1
loop
0 ->y1
#Do the next box next time.
<-y0 6 add dup ->y0 MapHeight gte if
0 ->y0
<-x0 6 add dup ->x0 MapWidth gte if
0 ->x0
#Unless you get to the end then trigger cleaning.
FALSE ->isRendering
TRUE ->isCleaning
0 ->y0
0 ->x1
0 ->y1
"Left click to zoom
Right click to start" SetText
"Retro23" PlaySound
return
else
<-x0 12 mod eq0 if "Misc9" else "Misc14" endif PlaySound
endif
endif
"Rendering:
" <-x0 <-y0 MapHeight asfloat div 5 mul add
MapWidth asfloat div 100 mul asint concat "%" concat SetText