diff --git a/lib/mom/callable_compiler.rb b/lib/mom/callable_compiler.rb new file mode 100644 index 00000000..352e8a55 --- /dev/null +++ b/lib/mom/callable_compiler.rb @@ -0,0 +1,74 @@ +module Mom + + # CallableCompiler is used to generate Mom instructions. + + # - mom_instructions: The sequence of mom level instructions that vool was compiled to + + class CallableCompiler + + def initialize( callable ) + @callable = callable + @constants = [] + @block_compilers = [] + @mom_instructions = Risc.label(source_name, source_name) + @current = start = @risc_instructions + add_code Risc.label( source_name, "return_label") + Mom::ReturnSequence.new.to_risc(self) + add_code Risc.label( source_name, "unreachable") + @current = start + end + attr_reader :risc_instructions , :constants , :block_compilers , :callable , :current + + def return_label + @risc_instructions.each do |ins| + next unless ins.is_a?(Label) + return ins if ins.name == "return_label" + end + end + + # convert the given mom instruction to_risc and then add it (see add_code) + # continue down the instruction chain unti depleted + # (adding moves the insertion point so the whole mom chain is added as a risc chain) + def add_mom( instruction ) + while( instruction ) + raise "whats this a #{instruction}" unless instruction.is_a?(Mom::Instruction) + #puts "adding mom #{instruction.to_s}:#{instruction.next.to_s}" + instruction.to_risc( self ) + reset_regs + #puts "adding risc #{risc.to_s}:#{risc.next.to_s}" + instruction = instruction.next + end + end + + # add a constant (which get created during compilation and need to be linked) + def add_constant(const) + raise "Must be Parfait #{const}" unless const.is_a?(Parfait::Object) + @constants << const + end + + # add a risc instruction after the current (insertion point) + # the added instruction will become the new insertion point + def add_code( instruction ) + raise "Not an instruction:#{instruction.to_s}:#{instruction.class.name}" unless instruction.is_a?(Risc::Instruction) + raise instruction.to_s if( instruction.class.name.split("::").first == "Arm") + new_current = instruction.last #after insertion this point is lost + @current.insert(instruction) #insert after current + @current = new_current + self + end + + # return the frame type, ie the blocks frame type + def frame_type + @callable.frame_type + end + # return the frame type, ie the blocks arguments type + def arg_type + @callable.arguments_type + end + # return the frame type, ie the blocks self_type + def receiver_type + @callable.self_type + end + + end +end diff --git a/lib/mom/mom.rb b/lib/mom/mom.rb index 2fec938e..b93a2f3e 100644 --- a/lib/mom/mom.rb +++ b/lib/mom/mom.rb @@ -16,3 +16,4 @@ end require_relative "instruction/instruction.rb" require_relative "mom_compiler" +require_relative "callable_compiler" diff --git a/lib/parfait/vool_method.rb b/lib/parfait/vool_method.rb index 8e3ff8be..8059b6fa 100644 --- a/lib/parfait/vool_method.rb +++ b/lib/parfait/vool_method.rb @@ -14,7 +14,7 @@ module Parfait attr :type, :name , :args_type , :frame_type attr_reader :source - + def initialize(name , args_type , frame_type , source ) self.name = name self.args_type = args_type @@ -34,7 +34,7 @@ module Parfait def compiler_for(self_type) callable_method = create_callable_method(self_type) - compiler = Risc::MethodCompiler.new( callable_method ) + compiler = Mom::CallableCompiler.new( callable_method ) head = @source.to_mom( compiler ) compiler.add_mom(head) compiler diff --git a/test/mom/test_callable_compiler.rb b/test/mom/test_callable_compiler.rb new file mode 100644 index 00000000..5ba6c0c3 --- /dev/null +++ b/test/mom/test_callable_compiler.rb @@ -0,0 +1,40 @@ +require_relative "helper" + +module Mom + class TestMomCompiler < MiniTest::Test + include MomCompile + + def setup + Parfait.boot!(Parfait.default_test_options) + @comp = compile_mom( "class Test ; def main(); return 'Hi'; end; end;") + end + + def test_class + assert_equal MomCompiler , @comp.class + end + def test_compilers + assert_equal 23 , @comp.compilers.length + end + def test_boot_compilers + assert_equal 22 , @comp.boot_compilers.length + end + def test_compilers_bare + assert_equal 22 , MomCompiler.new.compilers.length + end + def test_returns_constants + assert_equal Array , @comp.constants.class + end + def test_has_constant + assert_equal "Hi" , @comp.constants[1].to_string + end + def test_has_translate + assert @comp.translate(:interpreter) + end + def test_append_class + assert_equal MomCompiler, (@comp.append @comp).class + end + def test_append_length + assert_equal 2 , @comp.append(@comp).method_compilers.length + end + end +end diff --git a/test/parfait/test_vool_method.rb b/test/parfait/test_vool_method.rb new file mode 100644 index 00000000..c0314bf6 --- /dev/null +++ b/test/parfait/test_vool_method.rb @@ -0,0 +1,16 @@ +require_relative "helper" + +module Vool + class TestVoolMethod < MiniTest::Test + include MomCompile + + def setup + Parfait.boot!(Parfait.default_test_options) + @ins = compile_first_method( "@a = 5") + end + + def test_setup + + end + end +end diff --git a/test/vool/test_vool_method.rb b/test/vool/test_vool_method.rb new file mode 100644 index 00000000..c0314bf6 --- /dev/null +++ b/test/vool/test_vool_method.rb @@ -0,0 +1,16 @@ +require_relative "helper" + +module Vool + class TestVoolMethod < MiniTest::Test + include MomCompile + + def setup + Parfait.boot!(Parfait.default_test_options) + @ins = compile_first_method( "@a = 5") + end + + def test_setup + + end + end +end