lib/rasp/ast/flow.rb
# Contrary to my original expectation, not having used VBScript in
# ages, all three of (start, finish, step) are fixed at loop start.
Contrary to my original expectation, not having used VBScript in
ages, all three of (start, finish, step) are fixed at loop start.
Contrary to my original expectation not having used VBScript in ages all three of ( start finish step ) are fixed at loop start .
def bytecode(g)
    loop_var = g.state.scope.lookup_variable(g, var)
    @finish.bytecode(g)
    if @step
      @step.bytecode(g) if @step
      unless Rasp::AST::Literal === @step
        g.dup
        g.meta_push_0
        g.swap
        g.send :<, 1
      end
    end
    @start.bytecode(g)
    loop_var.set_bytecode(g)
    g.pop
    loop_body = g.new_label
    loop_body.set!
    @body.each do |s|
      s.bytecode(g)
    end
    if Rasp::AST::Literal === @step || @step.nil?
      if @step
        g.dup_many 2 
        loop_var.get_bytecode(g)
        g.send :+, 1
      else
        g.dup 
        loop_var.get_bytecode(g)
        g.send_vcall :succ
      end
      loop_var.set_bytecode(g)
      if @step.nil? || @step.value > 0
        g.swap
        g.send :>, 1
      elsif @step.value < 0
        g.swap
        g.send :<, 1
      else
        raise "For loop cannot have a zero step"
      end
      g.gif loop_body
      if @step
        g.pop_many 2
      else
        g.pop
      end
    else
       In theory, we could apply some clever logic based on the size of
       @body, to decide whether we're better off paying an extra git
       per iteration at runtime vs having two separate copies of the
       loop. No idea whether that'd be actually useful.
      check_backwards = g.new_label
      end_loop = g.new_label
      g.dup_many 3  loop_backwards, @step, @finish, ...
      loop_var.get_bytecode(g)
      g.send :+, 1
      loop_var.set_bytecode(g)
      g.git check_backwards
      g.swap
      g.send :>, 1
      g.gif loop_body
      g.goto end_loop
      check_backwards.set!
      g.swap
      g.send :<, 1
      g.gif loop_body
      end_loop.set!
      g.pop_many 3
    end
  end
def bytecode ( g ) loop_var = g . state . scope . lookup_variable ( g , var ) @finish . bytecode ( g ) if @step @step . bytecode ( g ) if @step unless Rasp :: AST :: Literal === @step g . dup g . meta_push_0 g . swap g . send :< , 1 end end @start . bytecode ( g ) loop_var . set_bytecode ( g ) g . pop loop_body = g . new_label loop_body . set! @body . each do | s | s . bytecode ( g ) end if Rasp :: AST :: Literal === @step || @step . nil? if @step g . dup_many 2 loop_var . get_bytecode ( g ) g . send :+ , 1 else g . dup loop_var . get_bytecode ( g ) g . send_vcall :succ end loop_var . set_bytecode ( g ) if @step . nil? || @step . value > 0 g . swap g . send :> , 1 elsif @step . value < 0 g . swap g . send :< , 1 else raise "For loop cannot have a zero step" end g . gif loop_body if @step g . pop_many 2 else g . pop end else check_backwards = g . new_label end_loop = g . new_label g . dup_many 3 loop_var . get_bytecode ( g ) g . send :+ , 1 loop_var . set_bytecode ( g ) g . git check_backwards g . swap g . send :> , 1 g . gif loop_body g . goto end_loop check_backwards . set! g . swap g . send :< , 1 g . gif loop_body end_loop . set! g . pop_many 3 end end
Contrary to my original expectation, not having used VBScript in
ages, all three of (start, finish, step) are fixed at loop start.
Contrary to my original expectation not having used VBScript in ages all three of ( start finish step ) are fixed at loop start .
# Step is constant # @step, @finish, ... # @finish, ... # Always working forwards # Always working backwards # Constant step of zero?! Twit. # Dynamic step; have to work out which way we're going at runtime # Experimentation shows this isn't as scary as it seems; the # reference implementation only evaluates the Step value once, as # the loop starts. # # In theory, we could apply some clever logic based on the size of # @body, to decide whether we're better off paying an extra git # per iteration at runtime vs having two separate copies of the # loop. No idea whether that'd be actually useful. # loop_backwards, @step, @finish, ...
g