Fix vool assignments after call rework
also small fix for if and return, as they need to execute sneds and yields (not just sends), so testing for Call not SendStatement
This commit is contained in:
parent
e6c30d98fb
commit
7c91a08d5b
@ -9,10 +9,10 @@ module Ruby
|
||||
end
|
||||
|
||||
def to_vool
|
||||
val , rest = *normalize_name(@return_value)
|
||||
me = Vool::ReturnStatement.new(val.to_vool)
|
||||
return me unless rest
|
||||
Vool::Statements.new([ rest.to_vool , me])
|
||||
val , hoisted = *normalized_vool(@return_value)
|
||||
me = Vool::ReturnStatement.new(val)
|
||||
return me unless hoisted
|
||||
Vool::Statements.new( hoisted ) << me
|
||||
end
|
||||
|
||||
def to_s(depth = 0)
|
||||
|
@ -1,5 +1,10 @@
|
||||
module Vool
|
||||
|
||||
# Base class for assignments (local/ivar), works just as you'd expect
|
||||
# Only "quirk" maybe, that arguments are like locals
|
||||
#
|
||||
# Only actual functionality here is the compile_assign_call which compiles
|
||||
# the call, should the assigned value be a call.
|
||||
class Assignment < Statement
|
||||
attr_reader :name , :value
|
||||
def initialize(name , value )
|
||||
@ -19,9 +24,18 @@ module Vool
|
||||
at_depth(depth , "#{@name} = #{@value}")
|
||||
end
|
||||
|
||||
def chain_assign(assign , compiler)
|
||||
# The assign instruction (a slot_load) is produced by delegating the slot to derived
|
||||
# class
|
||||
#
|
||||
# When the right hand side is a CallStatement, it must be compiled, before the assign
|
||||
# is executed
|
||||
#
|
||||
# Derived classes do not implement to_mom, only slot_position
|
||||
def to_mom(compiler)
|
||||
to = Mom::SlotDefinition.new(:message , self.slot_position(compiler))
|
||||
from = @value.slot_definition(compiler)
|
||||
assign = Mom::SlotLoad.new(self,to,from)
|
||||
return assign unless @value.is_a?(CallStatement)
|
||||
raise "Move me to ruby layer"
|
||||
@value.to_mom(compiler) << assign
|
||||
end
|
||||
end
|
||||
|
@ -16,7 +16,7 @@ module Vool
|
||||
merge_label = Mom::Label.new( self , "merge_label_#{object_id.to_s(16)}")
|
||||
|
||||
check = Mom::TruthCheck.new(condition.slot_definition(compiler) , false_label)
|
||||
if @condition.is_a?(SendStatement)
|
||||
if @condition.is_a?(CallStatement)
|
||||
head = @condition.to_mom(compiler)
|
||||
head << check
|
||||
else
|
||||
|
@ -3,13 +3,16 @@ module Vool
|
||||
class IvarAssignment < Assignment
|
||||
|
||||
def to_s(depth = 0)
|
||||
"@#{super(depth)}"
|
||||
at_depth(depth,"@#{super(0)}")
|
||||
end
|
||||
|
||||
def to_mom( compiler )
|
||||
to = Mom::SlotDefinition.new(:message ,[ :receiver , @name])
|
||||
from = @value.slot_definition(compiler)
|
||||
return chain_assign( Mom::SlotLoad.new(self,to,from) , compiler)
|
||||
# We return the position where the local is stored. This is an array, giving the
|
||||
# position relative to :message- A SlotLoad is constructed from this.
|
||||
#
|
||||
# As we know it is a instance variable, it is stored in the :receiver , and has
|
||||
# the name @name
|
||||
def slot_position( compiler )
|
||||
[ :receiver , @name]
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,12 +1,16 @@
|
||||
module Vool
|
||||
|
||||
# Local assignment really only differs in where the variable is actually stored,
|
||||
# slot_position defines that
|
||||
class LocalAssignment < Assignment
|
||||
|
||||
def to_mom( compiler )
|
||||
slot_def = compiler.slot_type_for(@name)
|
||||
to = Mom::SlotDefinition.new(:message ,slot_def)
|
||||
from = @value.slot_definition(compiler)
|
||||
return chain_assign( Mom::SlotLoad.new(self,to,from) , compiler)
|
||||
# We return the position where the local is stored. This is an array, giving the
|
||||
# position relative to :message- A SlotLoad is constructed from this.
|
||||
#
|
||||
# Only snag is that we do not know this position, as only the compiler knows
|
||||
# if the variable name is a local or an arg. So we delegate to the compiler.
|
||||
def slot_position( compiler )
|
||||
compiler.slot_type_for(@name)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -18,7 +18,7 @@ module Vool
|
||||
def to_mom( compiler )
|
||||
load = Mom::SlotLoad.new( self , [:message , :return_value] ,
|
||||
@return_value.slot_definition(compiler) )
|
||||
if @return_value.is_a?(SendStatement)
|
||||
if @return_value.is_a?(CallStatement)
|
||||
ret = @return_value.to_mom(compiler)
|
||||
ret << load
|
||||
else
|
||||
|
@ -2,7 +2,18 @@ module Vool
|
||||
class Statements < Statement
|
||||
attr_reader :statements
|
||||
def initialize(statements)
|
||||
@statements = statements
|
||||
case statements
|
||||
when nil
|
||||
@statements = []
|
||||
when Array
|
||||
@statements = statements
|
||||
when Statement
|
||||
@statements = statements.statements
|
||||
when Statement
|
||||
@statements = [statements]
|
||||
else
|
||||
raise "Invalid class, must be Statement or Array, not #{statements.class}"
|
||||
end
|
||||
end
|
||||
|
||||
def empty?
|
||||
@ -24,7 +35,11 @@ module Vool
|
||||
@statements[i]
|
||||
end
|
||||
def <<(o)
|
||||
@statements << o
|
||||
if(o.is_a?(Statements))
|
||||
o.each {|s| @statements << s }
|
||||
else
|
||||
@statements << o
|
||||
end
|
||||
self
|
||||
end
|
||||
def prepend(o)
|
||||
|
@ -8,8 +8,26 @@ module Ruby
|
||||
def setup
|
||||
@lst = compile( "@foo = a.call(b)").to_vool
|
||||
end
|
||||
def test_s
|
||||
assert_equal "" , @lst.to_s
|
||||
def test_class
|
||||
assert_equal Vool::Statements , @lst.class
|
||||
end
|
||||
def test_first_class
|
||||
assert_equal Vool::LocalAssignment , @lst[0].class
|
||||
end
|
||||
def test_first_name
|
||||
assert @lst[0].name.to_s.start_with?("tmp_")
|
||||
end
|
||||
def test_second_class
|
||||
assert_equal Vool::LocalAssignment , @lst[1].class
|
||||
end
|
||||
def test_second_name
|
||||
assert @lst[1].name.to_s.start_with?("tmp_")
|
||||
end
|
||||
def test_last_class
|
||||
assert_equal Vool::IvarAssignment , @lst[2].class
|
||||
end
|
||||
def test_second_name
|
||||
assert_equal :foo, @lst[2].name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,28 +1,6 @@
|
||||
require_relative "helper"
|
||||
|
||||
module Ruby
|
||||
class TestReturnStatementVool < MiniTest::Test
|
||||
include RubyTests
|
||||
|
||||
def test_return_const
|
||||
lst = compile( "return 1" ).to_vool
|
||||
assert_equal Vool::ReturnStatement , lst.class
|
||||
end
|
||||
def test_return_value
|
||||
lst = compile( "return 1" ).to_vool
|
||||
assert_equal 1 , lst.return_value.value
|
||||
end
|
||||
|
||||
def test_return_send
|
||||
lst = compile( "return foo" ).to_vool
|
||||
assert_equal Vool::LocalAssignment , lst.first.class
|
||||
end
|
||||
def test_return_send
|
||||
lst = compile( "return foo" ).to_vool
|
||||
assert lst.last.return_value.name.to_s.start_with?("tmp_")
|
||||
assert_equal 2, lst.length
|
||||
end
|
||||
end
|
||||
class TestReturnStatement < MiniTest::Test
|
||||
include RubyTests
|
||||
|
||||
@ -43,4 +21,31 @@ module Ruby
|
||||
end
|
||||
|
||||
end
|
||||
class TestReturnStatementVool < MiniTest::Test
|
||||
include RubyTests
|
||||
|
||||
def test_return_const
|
||||
lst = compile( "return 1" ).to_vool
|
||||
assert_equal Vool::ReturnStatement , lst.class
|
||||
end
|
||||
def test_return_value
|
||||
lst = compile( "return 1" ).to_vool
|
||||
assert_equal 1 , lst.return_value.value
|
||||
end
|
||||
|
||||
def test_return_send
|
||||
lst = compile( "return foo" ).to_vool
|
||||
assert_equal Vool::ReturnStatement , lst.class
|
||||
end
|
||||
def test_return_send3
|
||||
lst = compile( "return foo.bar.zoo" ).to_vool
|
||||
assert_equal Vool::LocalAssignment , lst.first.class
|
||||
assert lst.first.name.to_s.start_with?("tmp_")
|
||||
end
|
||||
def test_return_send4
|
||||
lst = compile( "return foo.bar.zoo" ).to_vool
|
||||
assert_equal Vool::ReturnStatement, lst[2].class
|
||||
assert_equal :zoo, lst[2].return_value.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user