Skip to content
This repository has been archived by the owner on May 13, 2019. It is now read-only.

Commit

Permalink
For loop appears to be working now.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewd committed Nov 20, 2010
1 parent d21fcee commit c6c4daf
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 33 deletions.
54 changes: 23 additions & 31 deletions lib/rasp/ast/flow.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -59,71 +59,66 @@ def initialize(var, start, finish, step, body)
@var, @start, @finish, @step = var, start, finish, step @var, @start, @finish, @step = var, start, finish, step
end end
def bytecode(g) def bytecode(g)
# FIXME
if g.state.scope.variables.key? var if g.state.scope.variables.key? var
loop_var = g.state.scope.variable(var).reference loop_var = g.state.scope.variable(var).reference
else else
loop_var = g.state.scope.global.variable(var).reference loop_var = g.state.scope.global.variable(var).reference
end end


finish_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
@finish.bytecode(g) @finish.bytecode(g)
finish_var.set_bytecode(g) if @step

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

@step.bytecode(g) if @step @step.bytecode(g) if @step
g.dup unless Rasp::AST::Literal === @step
step_var.set_bytecode(g) g.dup
g.meta_push_0 g.meta_push_0
g.send_stack :<, 1 g.send :<, 1
dir_var.set_bytecode(g) end
end end


@start.bytecode(g) @start.bytecode(g)
loop_var.set_bytecode(g) loop_var.set_bytecode(g)
g.pop


loop_body = g.new_label loop_body = g.new_label
loop_body.set! loop_body.set!


@body.each do |s| @body.each do |s|
#s.bytecode(g) s.bytecode(g)
end end


if Rasp::AST::Literal === @step || @step.nil? if Rasp::AST::Literal === @step || @step.nil?
# Step is constant # Step is constant


if @step if @step
@step.bytecode(g) g.dup_many 2 # @step, @finish, ...
loop_var.get_bytecode(g) loop_var.get_bytecode(g)
g.send_stack :+, 1 g.send :+, 1
else else
g.dup # @finish, ...
loop_var.get_bytecode(g) loop_var.get_bytecode(g)
g.send_vcall :inc g.send_vcall :inc
end end
g.dup
loop_var.set_bytecode(g) loop_var.set_bytecode(g)
finish_var.get_bytecode(g)
g.swap


if @step.nil? || @step.value > 0 if @step.nil? || @step.value > 0
# Always working forwards # Always working forwards
g.send_stack :>, 1 g.send :>, 1
elsif @step.value < 0 elsif @step.value < 0
# Always working backwards # Always working backwards
g.send_stack :<, 1 g.send :<, 1
else else
# Constant step of zero?! Twit. # Constant step of zero?! Twit.
raise "For loop cannot have a zero step" raise "For loop cannot have a zero step"
end end


g.gif loop_body 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 else
raise "dynstep!"
# Dynamic step; have to work out which way we're going at runtime # Dynamic step; have to work out which way we're going at runtime
# Experimentation shows this isn't as scary as it seems; the # Experimentation shows this isn't as scary as it seems; the
# reference implementation only evaluates the Step value once, as # reference implementation only evaluates the Step value once, as
Expand All @@ -137,25 +132,22 @@ def bytecode(g)
check_backwards = g.new_label check_backwards = g.new_label
end_loop = g.new_label end_loop = g.new_label


finish_var.get_bytecode(g) g.dup_many 3 # loop_backwards, @step, @finish, ...
step_var.get_bytecode(g)
loop_var.get_bytecode(g) loop_var.get_bytecode(g)
g.send_stack :+, 1 g.send :+, 1
g.dup
loop_var.set_bytecode(g) loop_var.set_bytecode(g)


dir_var.get_bytecode(g)
g.git check_backwards g.git check_backwards

g.send :>, 1
g.send_stack :>, 1
g.gif loop_body g.gif loop_body
g.goto end_loop g.goto end_loop


check_backwards.set! check_backwards.set!
g.send_stack :<, 1 g.send :<, 1
g.gif loop_body g.gif loop_body


end_loop.set! end_loop.set!
g.pop_many 3
end end
end end
end end
Expand Down
4 changes: 3 additions & 1 deletion lib/rasp/ast/simple.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ def initialize(vars)
@vars = vars @vars = vars
end end
def bytecode(g) def bytecode(g)
# Compiler directive vars.each do |var|
g.state.scope.variable(var)
end
end end
end end
class ErrorControl < Statement class ErrorControl < Statement
Expand Down
2 changes: 1 addition & 1 deletion lib/rasp/parser.citrus
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ grammar Rasp::Parser
end end
rule for_next 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) (`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 end
rule single_line_if 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) ) (`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) )
Expand Down

0 comments on commit c6c4daf

Please sign in to comment.