Permalink
Browse files

For loop appears to be working now.

  • Loading branch information...
1 parent d21fcee commit c6c4dafea9a1a2671fc16b387d6626002307d4bc @matthewd committed Nov 20, 2010
Showing with 27 additions and 33 deletions.
  1. +23 −31 lib/rasp/ast/flow.rb
  2. +3 −1 lib/rasp/ast/simple.rb
  3. +1 −1 lib/rasp/parser.citrus
View
@@ -59,71 +59,66 @@ def initialize(var, start, finish, step, body)
@var, @start, @finish, @step = var, start, finish, step
end
def bytecode(g)
- # FIXME
if g.state.scope.variables.key? var
loop_var = g.state.scope.variable(var).reference
else
loop_var = g.state.scope.global.variable(var).reference
end
- finish_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
@finish.bytecode(g)
- finish_var.set_bytecode(g)
-
- unless Rasp::AST::Literal === @step || @step.nil?
- step_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
- dir_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
-
+ if @step
@step.bytecode(g) if @step
- g.dup
- step_var.set_bytecode(g)
- g.meta_push_0
- g.send_stack :<, 1
- dir_var.set_bytecode(g)
+ unless Rasp::AST::Literal === @step
+ g.dup
+ g.meta_push_0
+ 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)
+ s.bytecode(g)
end
if Rasp::AST::Literal === @step || @step.nil?
# Step is constant
if @step
- @step.bytecode(g)
+ g.dup_many 2 # @step, @finish, ...
loop_var.get_bytecode(g)
- g.send_stack :+, 1
+ g.send :+, 1
else
+ g.dup # @finish, ...
loop_var.get_bytecode(g)
g.send_vcall :inc
end
- g.dup
loop_var.set_bytecode(g)
- finish_var.get_bytecode(g)
- g.swap
if @step.nil? || @step.value > 0
# Always working forwards
- g.send_stack :>, 1
+ g.send :>, 1
elsif @step.value < 0
# Always working backwards
- g.send_stack :<, 1
+ g.send :<, 1
else
# Constant step of zero?! Twit.
raise "For loop cannot have a zero step"
end
g.gif loop_body
- # finish_var is done now; can we get rid of it?
+ if @step
+ g.pop_many 2
+ else
+ g.pop
+ end
else
- raise "dynstep!"
# 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
@@ -137,25 +132,22 @@ def bytecode(g)
check_backwards = g.new_label
end_loop = g.new_label
- finish_var.get_bytecode(g)
- step_var.get_bytecode(g)
+ g.dup_many 3 # loop_backwards, @step, @finish, ...
loop_var.get_bytecode(g)
- g.send_stack :+, 1
- g.dup
+ g.send :+, 1
loop_var.set_bytecode(g)
- dir_var.get_bytecode(g)
g.git check_backwards
-
- g.send_stack :>, 1
+ g.send :>, 1
g.gif loop_body
g.goto end_loop
check_backwards.set!
- g.send_stack :<, 1
+ g.send :<, 1
g.gif loop_body
end_loop.set!
+ g.pop_many 3
end
end
end
View
@@ -37,7 +37,9 @@ def initialize(vars)
@vars = vars
end
def bytecode(g)
- # Compiler directive
+ vars.each do |var|
+ g.state.scope.variable(var)
+ end
end
end
class ErrorControl < Statement
View
@@ -77,7 +77,7 @@ grammar Rasp::Parser
end
rule for_next
(`for` SP identifier SP? "=" SP? start:expression SP `to` SP finish:expression (SP `step` SP step:expression)? ENDSTATEMENT body:(statement*) `next` ENDSTATEMENT)
- { Rasp::AST::ForLoop.new(identifier.value, start.value, finish.value, first(:step) && first(:step).value, body.matches.map {|m| m.value }) }
+ { Rasp::AST::ForLoop.new(identifier.value, start.value, finish.value, first(:step) && first(:step).value, body.matches.map {|m| m.value }.compact) }
end
rule single_line_if
(`if` SP expression SP `then` SP truepart:(single:single_line_if { [single] } | list:simple_statement_chain) (SP `else` SP falsepart:(single:single_line_if | list:simple_statement_chain EOL) | EOL) )

0 comments on commit c6c4daf

Please sign in to comment.