diff --git a/lib/risc/builder.rb b/lib/risc/builder.rb index f8f5daab..fecf43fa 100644 --- a/lib/risc/builder.rb +++ b/lib/risc/builder.rb @@ -77,11 +77,26 @@ module Risc @source_used = true add_code Risc::IsNotZero.new(@source , label) end + def if_minus( label ) + @source_used = true + add_code Risc::IsMinus.new(@source , label) + end def branch( label ) @source_used = true add_code Risc::Branch.new(@source, label) end + # to avoid many an if, it can be candy to swap variable names. + # but since the names in the builder are not variables, we need this method + # as it says, swap the two names around. Names must exist + def swap_names(left , right) + l = @names[left] + r = @names[right] + raise "No such name #{left}" unless l + raise "No such name #{right}" unless r + @names[left] = r + @names[right] = l + end # build code using dsl (see __init__ or MessageSetup for examples) # names (that ruby would resolve to a variable/method) are converted # to registers. << means assignment and [] is supported both on diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb index 6d4f9f58..60852be5 100644 --- a/lib/risc/builtin/integer.rb +++ b/lib/risc/builtin/integer.rb @@ -33,28 +33,27 @@ module Risc def comparison( operator ) compiler = compiler_for(:Integer, operator ,{other: :Integer}) builder = compiler.compiler_builder(compiler.source) - me , other = builder.self_and_int_arg("#{operator} load receiver and arg") - false_label = Risc.label(compiler.source , "false_label_#{builder.object_id.to_s(16)}") - merge_label = Risc.label(compiler.source , "merge_label_#{builder.object_id.to_s(16)}") - builder.reduce_int( "#{operator} fix me", me ) - builder.reduce_int( "#{operator} fix arg", other ) - if(operator.to_s.start_with?('<') ) - me , other = other , me + builder.build do + integer << message[:receiver] + integer_reg << message[:arguments] + integer_reg << integer_reg[ 1] + integer.reduce_int + integer_reg.reduce_int + swap_names(:integer , :integer_reg) if(operator.to_s.start_with?('<') ) + integer.op :- , integer_reg + if_minus false_label + if_zero( false_label ) if operator.to_s.length == 1 + object << Parfait.object_space.true_object + branch merge_label + add_code false_label + object << Parfait.object_space.false_object + add_code merge_label + message[:return_value] << object end - builder.add_code Risc.op( "#{operator} operator", :- , me , other) - builder.add_code IsMinus.new( "#{operator} if", false_label) - if(operator.to_s.length == 1) - builder.add_code IsZero.new( "#{operator} if", false_label) - end - builder.add_load_constant("#{operator} new int", Parfait.object_space.true_object , other) - builder.add_code Risc::Branch.new("jump over false", merge_label) - builder.add_code false_label - builder.add_load_constant("#{operator} new int", Parfait.object_space.false_object , other) - builder.add_code merge_label - builder.add_reg_to_slot( "#{operator} save ret" , other , Risc.message_reg , :return_value) compiler.add_mom( Mom::ReturnSequence.new) return compiler end + def putint(context) compiler = compiler_for(:Integer,:putint ,{}) compiler.add_mom( Mom::ReturnSequence.new) diff --git a/test/risc/test_builder1.rb b/test/risc/test_builder1.rb index 1b3aac16..6362e5c5 100644 --- a/test/risc/test_builder1.rb +++ b/test/risc/test_builder1.rb @@ -14,7 +14,23 @@ module Risc r1 = RegisterValue.new(:r1 , :Space) @builder.build{ space << r1 } assert_equal Transfer , @compiler.risc_instructions.next.class + assert_equal RegisterValue , @builder.space.class + end + def test_loads + @builder.build{ space << Parfait.object_space } + assert_equal LoadConstant , @compiler.risc_instructions.next.class + assert_equal RegisterValue , @builder.space.class + end + def test_two + @builder.build{ space << Parfait.object_space ; integer << 1} + assert_equal LoadConstant , @compiler.risc_instructions.next.class + assert_equal LoadData , @compiler.risc_instructions.next(2).class + end + def test_swap + test_two + @builder.swap_names( :space , :integer) + assert_equal :Integer , @builder.space.type.class_name + assert_equal :Space , @builder.integer.type.class_name end - end end