fix argument hoisting

arguments in vool must be simple variables
finally did the hoisting to do that
This commit is contained in:
Torsten Ruger 2018-04-27 09:59:01 +03:00
parent 08d0aae79e
commit 672ccb351d
4 changed files with 76 additions and 12 deletions

View File

@ -16,7 +16,9 @@ module Vool
def ct_type
Parfait.object_space.get_class_by_name(:Integer).instance_type
end
#gobble it up
def to_s
value.to_s
end
def each(&block)
end
end
@ -65,6 +67,9 @@ module Vool
def ct_type
@my_type
end
def to_s
"self"
end
end
class SuperExpression < Statement
end

View File

@ -18,16 +18,31 @@ module Vool
end
def normalize
#TODO normalize arguments. In first stage args must be variables or hoisted (like while/if)
# later sends ok, but then they must execute
# (currently we only use the args as slot_definition so they are not "momed")
@arguments.each_with_index do |arg , index |
raise "arg #{index} does not provide slot definition #{arg}" unless arg.respond_to?(:slot_definition)
raise "Sends not implemented yet at #{index}:#{arg}" if arg.is_a?(SendStatement)
statements = Statements.new([])
arguments = []
@arguments.dup.each_with_index do |arg , index |
normalize_arg(arg , arguments , statements)
end
SendStatement.new(@name, @receiver , @arguments)
if statements.empty?
return SendStatement.new(@name, @receiver , @arguments)
else
statements << SendStatement.new(@name, @receiver , arguments)
return statements
end
end
def normalize_arg(arg , arguments , statements)
if arg.respond_to?(:slot_definition) and !arg.is_a?(SendStatement)
arguments << arg
return
end
assign = LocalAssignment.new( "tmp_#{arg.object_id}".to_sym, arg)
statements << assign
arguments << assign.name
end
def to_s
"#{receiver}.#{name}(#{arguments.join(',')})"
end
def each(&block)
block.call(self)
block.call(@receiver)
@ -44,10 +59,6 @@ module Vool
# A Send breaks down to 2 steps:
# - Setting up the next message, with receiver, arguments, and (importantly) return address
# - a CachedCall , or a SimpleCall, depending on wether the receiver type can be determined
#
# FIXME: we now presume direct (assignable) values for the arguments and receiver.
# in a not so distant future, temporary variables will have to be created
# and complex statements hoisted to assign to them. pps: same as in conditions
def to_mom( in_method )
@receiver = SelfExpression.new(in_method.for_type) if @receiver.is_a?(SelfExpression)
if(@receiver.ct_type)

View File

@ -0,0 +1,13 @@
require_relative "../helper"
module Vool
module Norm
class NormTest < MiniTest::Test
def normalize(input)
RubyCompiler.compile(input).normalize
end
end
end
end

View File

@ -0,0 +1,35 @@
require_relative "helper"
module Vool
module Norm
class TestSendSimple < NormTest
def test_simple
lst = normalize("foo")
assert_equal SendStatement , lst.class
end
def test_constant_args
lst = normalize("foo(1,2)")
assert_equal SendStatement , lst.class
end
end
class TestSendSend < NormTest
def setup
super
@stm = normalize("foo(1 - 2)")
end
def test_many
assert_equal Statements , @stm.class
end
def test_assignment
assert_equal LocalAssignment , @stm.first.class
end
def test_name
assert @stm.first.name.to_s.start_with?("tmp_") , @stm.first.name
end
def test_assigned
assert_equal SendStatement , @stm.first.value.class
end
end
end
end