Class: CodeDoTimesInstruction

Inherits:
Instruction show all
Defined in:
lib/instructions/code/code_do_times.rb

Overview

Pops two values from the :int stack (“destination” and “counter”), and one item from the :code 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).

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

note: unlike the CodeDoRange instruction, the counter is not pushed

If the counter and destination have the same value, then a copy of the :code 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_times
  popped item
}
«int» new_counter
«int» destination

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

Finally,

  1. the macro is pushed onto the :exec stack

  2. 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, then 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: ExecDoTimesInstruction must be active; 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



66
67
68
69
70
71
72
73
74
75
# File 'lib/instructions/code/code_do_times.rb', line 66

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

#deriveObject



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/instructions/code/code_do_times.rb', line 54

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
  @codeblock = NudgeProgram.new(@code).linked_code
end

#preconditions?Boolean

Returns:

  • (Boolean)


42
43
44
45
46
# File 'lib/instructions/code/code_do_times.rb', line 42

def preconditions?
  needs ExecDoTimesInstruction
  needs :code, 1
  needs :int, 2
end

#setupObject



48
49
50
51
52
# File 'lib/instructions/code/code_do_times.rb', line 48

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