diff --git a/lib/mom/instruction/message_setup.rb b/lib/mom/instruction/message_setup.rb index f80a7582..9ef8c6ba 100644 --- a/lib/mom/instruction/message_setup.rb +++ b/lib/mom/instruction/message_setup.rb @@ -35,7 +35,7 @@ module Mom # but also used directly in __init def build_with(builder) from = method_source - risc = builder.build { typed_method << from } + risc = builder.build_and_return { typed_method << from } risc << build_message_data(builder) builder.compiler.reset_regs return risc @@ -50,7 +50,7 @@ module Mom # also put it into next_message of current message (and reverse) # set name and type data in the message, from the method loaded def build_message_data( builder ) - builder.build do + builder.build_and_return do space << Parfait.object_space next_message << space[:first_message] message[:next_message] << next_message diff --git a/lib/risc/builder.rb b/lib/risc/builder.rb index 3504eddf..b36ce0ad 100644 --- a/lib/risc/builder.rb +++ b/lib/risc/builder.rb @@ -4,11 +4,16 @@ module Risc attr_reader :built , :compiler + # pass a compiler, to which instruction are added (usually) + # call build or build_and_return with a block def initialize(compiler) @compiler = compiler @names = {} end + # make the magic: convert incoming names into registers that have the + # type set according to the name (using resolve_type) + # anmes are stored, so subsequent calls use the same register def method_missing(*args) super if args.length != 1 name = args[0] @@ -24,17 +29,32 @@ module Risc reg 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 + # L and R values (but only one at a time). R values may also be constants. + # Basically this allows to create LoadConstant, RegToSlot, SlotToReg and + # Transfer instructions with extremely readable code. + # example: + # space << Parfait.object_space # load constant + # message[:receiver] << space #make current message (r0) receiver the space + # + # build result is available as built, but also gets added to compiler def build(&block) - @built = nil - instance_eval(&block) - return @built + risc = build_and_return(&block) + @compiler.add_code(risc) + risc end - def build_and_add(&block) - risc = build(&block) - @compiler.add_code(risc) + # version of build that does not add to compiler, just returns the code + def build_and_return(&block) + @built = nil + instance_eval(&block) + risc = @built + @built = nil + return risc end - + def add_instruction(ins) if(@built) @built << ins @@ -44,10 +64,6 @@ module Risc end end - def self.build(compiler, &block) - Builder.new(compiler).build( &block ) - end - # if a symbol is given, it may be the message or the new_message. # These are mapped to register references. # The valid symbols (:message,:new_message) are the same that are returned diff --git a/lib/risc/builtin/object.rb b/lib/risc/builtin/object.rb index 9c6a4931..99a7d472 100644 --- a/lib/risc/builtin/object.rb +++ b/lib/risc/builtin/object.rb @@ -47,7 +47,7 @@ module Risc compiler = Risc::MethodCompiler.create_method(:Object,:__init__ , Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({})) builder = Risc::Builder.new(compiler) - builder.build_and_add do + builder.build do space << Parfait.object_space message << space[:first_message] next_message << message[:next_message] @@ -57,7 +57,7 @@ module Risc risc = Mom::MessageSetup.new(Parfait.object_space.get_main).build_with( builder ) compiler.add_code(risc) - builder.build_and_add do + builder.build do message << message[:next_message] message[:receiver] << space end diff --git a/lib/risc/method_compiler.rb b/lib/risc/method_compiler.rb index 2fa99ecc..20bc6f02 100644 --- a/lib/risc/method_compiler.rb +++ b/lib/risc/method_compiler.rb @@ -79,7 +79,7 @@ module Risc instruction = instruction.next end end - + # add a risc instruction after the current (insertion point) # the added instruction will become the new insertion point def add_code( instruction ) @@ -170,5 +170,15 @@ module Risc def reduce_int( source , register ) add_slot_to_reg( source + "int -> fix" , register , Parfait::Integer.integer_index , register) end + + # Build with builder (see there), adding the created instructions + def build(&block) + builder.build_and_return(&block) + end + + # return a new builder that uses this compiler + def builder + Builder.new(self) + end end end diff --git a/test/risc/interpreter/test_dynamic_call.rb b/test/risc/interpreter/test_dynamic_call.rb index dfe8a229..5bec4ce8 100644 --- a/test/risc/interpreter/test_dynamic_call.rb +++ b/test/risc/interpreter/test_dynamic_call.rb @@ -20,9 +20,22 @@ module Risc SlotToReg, RegToSlot, SlotToReg, SlotToReg, SlotToReg, SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot, SlotToReg, LoadConstant, FunctionCall, Label, SlotToReg, - SlotToReg, SlotToReg, SlotToReg, Label, LoadConstant, - SlotToReg, OperatorInstruction, IsZero, Label, Transfer, - Syscall, NilClass] + SlotToReg, SlotToReg, SlotToReg, SlotToReg, Label, + LoadConstant, SlotToReg, OperatorInstruction, IsZero, SlotToReg, + OperatorInstruction, IsNotZero, Label, SlotToReg, Branch, + Label, LoadConstant, SlotToReg, OperatorInstruction, IsZero, + SlotToReg, OperatorInstruction, IsNotZero, Label, SlotToReg, + Branch, Label, LoadConstant, SlotToReg, OperatorInstruction, + IsZero, SlotToReg, OperatorInstruction, IsNotZero, Label, + SlotToReg, Branch, Label, LoadConstant, SlotToReg, + OperatorInstruction, IsZero, SlotToReg, OperatorInstruction, IsNotZero, + Label, SlotToReg, Branch, Label, LoadConstant, + SlotToReg, OperatorInstruction, IsZero, SlotToReg, OperatorInstruction, + IsNotZero, Label, SlotToReg, Branch, Label, + LoadConstant, SlotToReg, OperatorInstruction, IsZero, SlotToReg, + OperatorInstruction, IsNotZero, Label, SlotToReg, Branch, + Label, LoadConstant, SlotToReg, OperatorInstruction, IsZero, + Label, Transfer, Syscall, NilClass] #assert_equal 1 , get_return end diff --git a/test/risc/test_builder.rb b/test/risc/test_builder.rb index 838ffdea..53b549d7 100644 --- a/test/risc/test_builder.rb +++ b/test/risc/test_builder.rb @@ -6,8 +6,7 @@ module Risc def setup Risc.machine.boot init = Parfait.object_space.get_init - compiler = Risc::MethodCompiler.new( init ) - @builder = Builder.new(compiler) + @builder = Risc::MethodCompiler.new( init ).builder end def test_has_build assert @builder.respond_to?(:build)