refactor risc_collection

move code that operates on compiler to the compiler class
this leaves the collection thin, very thin indeed
This commit is contained in:
Torsten Rüger 2019-09-28 15:34:09 +03:00
parent 9f81d78767
commit dcbc3e17be
6 changed files with 106 additions and 117 deletions

View File

@ -24,8 +24,8 @@ module Mom
self
end
# Return all compilers, namely the MethodCompilers passed in, plus the
# boot_function's compilers (boot_compilers)
# Return all compilers, namely the MethodCompilers instanc,
# plus the init_compilers
def compilers
init_compilers
@method_compilers

View File

@ -123,5 +123,20 @@ module Risc
def builder( source)
Builder.new(self , source)
end
# compile the callable (method or block) to cpu
# return an Assembler that will then translate to binary
def translate_cpu(translator)
risc = @risc_instructions
cpu_instructions = risc.to_cpu(translator)
nekst = risc.next
while(nekst)
cpu = nekst.to_cpu(translator) # returning nil means no replace
cpu_instructions << cpu if cpu
nekst = nekst.next
end
Risc::Assembler.new(@callable , cpu_instructions )
end
end
end

View File

@ -30,5 +30,14 @@ module Risc
@block_compilers << compiler
end
# translate this method, which means the method itself and all blocks inside it
# returns the array (of assemblers) that you pass in as collection
def translate_method( translator , collection)
collection << translate_cpu( translator )
@block_compilers.each do |block_compiler|
collection << block_compiler.translate_cpu(translator)
end
collection
end
end
end

View File

@ -40,43 +40,12 @@ module Risc
def translate( platform_sym )
platform_sym = platform_sym.to_s.capitalize
platform = Risc::Platform.for(platform_sym)
assemblers = translate_methods( platform.translator )
assemblers = []
@method_compilers.each_compiler do |compiler|
compiler.translate_method( platform.translator , assemblers)
end
Risc::Linker.new(platform , assemblers , constants)
end
# go through all methods and translate them to cpu, given the translator
def translate_methods(translator)
collection = []
method_compilers.each_compiler do |compiler|
#puts "Translate method #{compiler.callable.name}"
translate_method(compiler , translator , collection)
end
collection
end
# translate one method, which means the method itself and all blocks inside it
# returns an array of assemblers
def translate_method( method_compiler , translator , collection)
collection << translate_cpu( method_compiler , translator )
method_compiler.block_compilers.each do |block_compiler|
collection << translate_cpu(block_compiler , translator)
end
collection
end
# compile the callable (method or block) to cpu
# return an Assembler that will then translate to binary
def translate_cpu(compiler , translator)
risc = compiler.risc_instructions
cpu_instructions = risc.to_cpu(translator)
nekst = risc.next
while(nekst)
cpu = nekst.to_cpu(translator) # returning nil means no replace
cpu_instructions << cpu if cpu
nekst = nekst.next
end
Risc::Assembler.new(compiler.callable , cpu_instructions )
end
end
end

View File

@ -7,30 +7,70 @@ module Mom
def setup
end
def in_test_vool(body = "@ivar = 5;return")
code = in_Test("def meth; #{body};end")
RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(code)
def in_test_vool(str)
vool = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_vool(in_Test(str))
vool.to_parfait
vool.to_mom(nil)
vool
end
def create_method(body = "@ivar = 5;return")
in_test_vool("def meth; #{body};end")
test = Parfait.object_space.get_class_by_name(:Test)
test.get_instance_method(:meth)
end
def test_method
in_test_vool()
method = Parfait.object_space.get_class_by_name(:Test).get_instance_method(:meth)
def test_method_has_source
method = create_method
assert_equal Vool::Statements , method.source.class
end
def test_method_has_no_locals
method = create_method
assert_equal 1 , method.frame_type.instance_length
end
def test_method_has_no_args
method = create_method
assert_equal 1 , method.args_type.instance_length
end
def test_creates_method_in_class
method = create_method
assert method , "No method created"
assert_equal Parfait::VoolMethod , method.class
end
def test_method_mom_col
mom = in_test_vool()
assert_equal Mom::MomCollection , mom.class
assert_equal Mom::MethodCompiler , mom.compilers.class
def test_creates_method_statement_in_class
clazz = in_test_vool("def meth; @ivar = 5 ;return;end")
assert_equal Vool::Statements , clazz.body.class
assert_equal Vool::MethodExpression , clazz.body.first.class
end
def test_compiles_risc
compiler = in_test_vool().compilers.to_risc
assert_equal Risc::MethodCompiler , compiler.class
assert_equal Risc::Label , compiler.risc_instructions.class
def test_callable_method_instance_type
in_test_vool("def meth; @ivar = 5; @ibar = 4;return;end")
test = Parfait.object_space.get_class_by_name(:Test)
method = test.instance_type.get_method(:meth)
assert_equal 1, method.self_type.variable_index(:ivar)
assert_equal 2, method.self_type.variable_index(:ibar)
end
def test_compiles_all_risc
compiler = in_test_vool().compilers.to_risc
assert_equal Risc::LoadConstant , compiler.risc_instructions.next.class
assert_equal 16 , compiler.risc_instructions.length
def test_callable_method_has_one_local
in_test_vool("def meth; local = 5 ; a = 6;return;end")
test = Parfait.object_space.get_class_by_name(:Test)
method = test.get_instance_method(:meth)
assert_equal 3 , method.frame_type.instance_length
assert_equal 1 , method.frame_type.variable_index(:local)
assert_equal 2 , method.frame_type.variable_index(:a)
end
def constant_setup(input)
mom = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(in_Test(input))
assert_equal Mom::MomCollection , mom.class
compiler = mom.method_compilers
assert_equal Mom::MethodCompiler , compiler.class
compiler
end
def test_return_label
compiler = constant_setup("def meth; return 'Hi';end")
assert_equal "return_label", compiler.return_label.name
end
end
end

View File

@ -5,72 +5,28 @@ module Risc
include ScopeHelper
def setup
code = in_Test("def meth; @ivar = 5;return ;end")
rubyx = RubyX::RubyXCompiler.new(RubyX.default_test_options)
@compiler = rubyx.ruby_to_mom(code).compilers.to_risc
end
def in_test_vool(str)
vool = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_vool(in_Test(str))
vool.to_parfait
vool.to_mom(nil)
vool
def test_compiles_risc
assert_equal Risc::MethodCompiler , @compiler.class
assert_equal Risc::Label , @compiler.risc_instructions.class
end
def create_method(body = "@ivar = 5;return")
in_test_vool("def meth; #{body};end")
test = Parfait.object_space.get_class_by_name(:Test)
test.get_instance_method(:meth)
def test_compiles_all_risc
assert_equal Risc::LoadConstant , @compiler.risc_instructions.next.class
assert_equal 16 , @compiler.risc_instructions.length
end
def test_method_has_source
method = create_method
assert_equal Vool::Statements , method.source.class
def test_translate_cpu
cpu = @compiler.translate_cpu(Platform.for(:arm).translator)
assert_equal Assembler , cpu.class
assert_equal :meth , cpu.callable.name
end
def test_method_has_no_locals
method = create_method
assert_equal 1 , method.frame_type.instance_length
end
def test_method_has_no_args
method = create_method
assert_equal 1 , method.args_type.instance_length
end
def test_creates_method_in_class
method = create_method
assert method , "No method created"
assert_equal Parfait::VoolMethod , method.class
end
def test_creates_method_statement_in_class
clazz = in_test_vool("def meth; @ivar = 5 ;return;end")
assert_equal Vool::Statements , clazz.body.class
assert_equal Vool::MethodExpression , clazz.body.first.class
end
def test_callable_method_instance_type
in_test_vool("def meth; @ivar = 5; @ibar = 4;return;end")
test = Parfait.object_space.get_class_by_name(:Test)
method = test.instance_type.get_method(:meth)
assert_equal 1, method.self_type.variable_index(:ivar)
assert_equal 2, method.self_type.variable_index(:ibar)
end
def test_callable_method_has_one_local
in_test_vool("def meth; local = 5 ; a = 6;return;end")
test = Parfait.object_space.get_class_by_name(:Test)
method = test.get_instance_method(:meth)
assert_equal 3 , method.frame_type.instance_length
assert_equal 1 , method.frame_type.variable_index(:local)
assert_equal 2 , method.frame_type.variable_index(:a)
end
def constant_setup(input)
mom = RubyX::RubyXCompiler.new(RubyX.default_test_options).ruby_to_mom(in_Test(input))
assert_equal Mom::MomCollection , mom.class
compiler = mom.method_compilers
assert_equal Mom::MethodCompiler , compiler.class
compiler
end
def test_return_label
compiler = constant_setup("def meth; return 'Hi';end")
assert_equal "return_label", compiler.return_label.name
def test_translate_method
ass = @compiler.translate_method(Platform.for(:arm).translator , [])
assert_equal Array , ass.class
assert_equal Assembler , ass.first.class
assert_equal :meth , ass.first.callable.name
end
end
end