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:
@ -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)
|
||||
|
Reference in New Issue
Block a user