How to implement a For-Loop?

Brietech

Senior Member
Given 2 commands like: For(variable,start_val,end_val,step_val)
Next(variable)

How would one implement this, while maintaining the ability to nest them?

my first thought was to store the following:
-step size
-variable
-address of "For" command
-address of command following the "next" command ("next++_addr")
-flag bit to say if you were in "for-mode" or not

So then, in psuedo-code:
"for_address:"
If (for_mode=1) then goto continue_for
else
for_ptr=for_ptr+1
pop for_address

"continue_for:"
If for_var > final_for_val then
for_mode <= 0
Program_Counter <=(next++_addr)
for_ptr <= for_ptr - 1
else
(execute code here)


With the code for the "next" command like:
var = var + 1
goto for_addr


This would still be incomplete, however, as I would still need to store a stack of the (next++_addr) addresses as well.

Sorry this turned into kind of a rant, I just need some insight into how a For-loop usually works in an interpreter, and my brain is apparently not working =) Hippy? Demonicpicaxeguy? Anyone else?
 

hippy

Technical Support
Staff member
The simplest (*) solution is the one chosen by the PICAXE ...<code><pre><font size=2 face='Courier'> var = startValue
L1:
<i>code </i>
If stepSign = + Then
var = var + stepValue
Else
var = var - stepValue
End If
If var &gt;= startValue And var &lt;= endValue Then L1 </font></pre></code> That evaluates the start, end and step values when used so if using variables they shouldn't be altered within the FOR-NEXT by the end-user unless that's intended. If you want the values evaluated before the FOR-NEXT is entered then you need to access the values pushed to the stack.

This can get messy because there are things deep down the stack which are needed. If you have an addressing mode which allows STACK[SP-OFFSET] as an operand it's easy. If only TOS ( top of stack ) is visible, you'll need to pop and store values in temporary storage.

Assuming you don't have STACK[SP-OFFSET] operands in your interpreted language, or don't have a stack, I'd say (1) use the PICAXE method of evaluation, if the end-user alters values then it's their problem, (2) think of FOR-NEXT in terms of WHILE-WEND or REPEAT-UNTIL with an initial assignment and an assigned increment just before the end. Knowing the way the step goes (+/-) you can simplify the terminating condition to only one comparison, but wrap-round under and overflow can then cause some odd behaviour.

Another way to do it is to have a special NEXT operand which is given the index variable, start, end, direction, step values and address of the statement after the FOR and the interpreter itself works out what to do, which is how the PICAXE actually works.

This is where the Real World (TM) collides with Virtual Machine Design; having to implement what the user wants efficiently. This may mean redesigning the VM instruction set, and guess what; you soon end up with an instruction set which is no longer RISC and looks more like 80x86 :)

The other killers to implement efficiently are LOOKUP and particularly BUTTON and LOOKDOWN.

(*) There's actually a simpler solution -- Don't support FOR-NEXT, make the end-user use DO-LOOP, WHILE-WEND or REPEAT-UNTIL. I find it very rare to use FOR-NEXT anyway except in example code, the alternatives aren't much harder to write, easier to optimise, and no worries about how FOR-NEXT might behave, and no stack or temporary storage needed.

Edited by - hippy on 20/07/2007 04:56:11
 

Brietech

Senior Member
Excellent, thank you! I think I will go with a Do-Loop format, as that looks very straightforward to implement and should fit nicely with my other code.

p.s. I'm well aware of the whole RISC vs. CISC debate. A number of my colleagues worked on the Itanium, PA-RISC and various SGI MIPS processor designs, and it's an endless source of lunchtable arguing =) My favorite processor is still M68k!
 
Top