Class: ExecDoRangeInstruction

Inherits:
Instruction show all
Defined in:
lib/instructions/exec/exec_do_range.rb

Overview

Pops two values from the :int stack (“destination” and “counter”), and one item from the :exec stack. The net effect of the instruction (unless interfered with by another operation) is to evaluate the :exec item once for every integer in the range (inclusive), and at the same time push the counter integer onto the :int stack.

note: the first integer popped is the “destination”, the second one the “counter” (regardless of their values or signs)

note: unlike the ExecDoTimes instruction, the counter is pushed

If the counter and destination have the same value, then a new :int is pushed with that value, and the :exec item is pushed onto the :exec stack.

If the counter and destination have different values, then a “new_counter” value is calculated that is *one step closer to the destination*.

A ValuePoint containing the following “macro” is created:

block {
  value «int»
  value «int»
  do exec_do_range
  popped item
}
«int» new_counter
«int» destination

where popped_item is the code from the :exec stack, and new_counter and destination are the numeric values that were derived above.

Finally,

  1. a new ValuePoint whose value is new_counter is pushed to the :int stack;

  2. the macro is pushed onto the :exec stack

  3. another copy of the popped_item is pushed onto the :exec stack (on top of the macro)

The consequence is that the original item will be executed, the counter will be pushed onto the :int stack, the macro will be encountered, and this process will repeat.

note: if the popped_item itself manipulates the :exec stack, “complicated behavior” may arise

needs: 2 :int items, 1 :exec item

pushes: well, it’s complicated…

Instance Attribute Summary

Attributes inherited from Instruction

#context

Instance Method Summary collapse

Methods inherited from Instruction

all_instructions, #go, inherited, #initialize, #needs, #pushes, to_nudgecode

Constructor Details

This class inherits a constructor from Instruction

Instance Method Details

#cleanupObject



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/instructions/exec/exec_do_range.rb', line 67

def cleanup
  if @finished
    pushes :int, @counter
    pushes :exec, @code
  else
    recursor = CodeblockPoint.new([@new_counter, @destination,
      InstructionPoint.new("exec_do_range"),@code])
    pushes :int, @counter
    pushes :exec, recursor
    pushes :exec, @code
  end
end

#deriveObject



56
57
58
59
60
61
62
63
64
65
# File 'lib/instructions/exec/exec_do_range.rb', line 56

def derive
  @finished = false
  if @counter.value == @destination.value
    @finished = true
  elsif @counter.value < @destination.value
    @new_counter = ValuePoint.new("int", @counter.value + 1)
  else
    @new_counter = ValuePoint.new("int", @counter.value - 1)
  end
end

#preconditions?Boolean

Returns:

  • (Boolean)


45
46
47
48
# File 'lib/instructions/exec/exec_do_range.rb', line 45

def preconditions?
  needs :exec, 1
  needs :int, 2
end

#setupObject



50
51
52
53
54
# File 'lib/instructions/exec/exec_do_range.rb', line 50

def setup
  @destination = @context.pop(:int)
  @counter = @context.pop(:int)
  @code = @context.pop(:exec)
end