change build names a little and document

This commit is contained in:
Torsten Ruger 2018-04-07 22:35:40 +03:00
parent 6d1beec407
commit 26cf911a5c
6 changed files with 59 additions and 21 deletions

View File

@ -35,7 +35,7 @@ module Mom
# but also used directly in __init # but also used directly in __init
def build_with(builder) def build_with(builder)
from = method_source from = method_source
risc = builder.build { typed_method << from } risc = builder.build_and_return { typed_method << from }
risc << build_message_data(builder) risc << build_message_data(builder)
builder.compiler.reset_regs builder.compiler.reset_regs
return risc return risc
@ -50,7 +50,7 @@ module Mom
# also put it into next_message of current message (and reverse) # also put it into next_message of current message (and reverse)
# set name and type data in the message, from the method loaded # set name and type data in the message, from the method loaded
def build_message_data( builder ) def build_message_data( builder )
builder.build do builder.build_and_return do
space << Parfait.object_space space << Parfait.object_space
next_message << space[:first_message] next_message << space[:first_message]
message[:next_message] << next_message message[:next_message] << next_message

View File

@ -4,11 +4,16 @@ module Risc
attr_reader :built , :compiler 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) def initialize(compiler)
@compiler = compiler @compiler = compiler
@names = {} @names = {}
end 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) def method_missing(*args)
super if args.length != 1 super if args.length != 1
name = args[0] name = args[0]
@ -24,15 +29,30 @@ module Risc
reg reg
end 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) def build(&block)
@built = nil risc = build_and_return(&block)
instance_eval(&block) @compiler.add_code(risc)
return @built risc
end end
def build_and_add(&block) # version of build that does not add to compiler, just returns the code
risc = build(&block) def build_and_return(&block)
@compiler.add_code(risc) @built = nil
instance_eval(&block)
risc = @built
@built = nil
return risc
end end
def add_instruction(ins) def add_instruction(ins)
@ -44,10 +64,6 @@ module Risc
end end
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. # if a symbol is given, it may be the message or the new_message.
# These are mapped to register references. # These are mapped to register references.
# The valid symbols (:message,:new_message) are the same that are returned # The valid symbols (:message,:new_message) are the same that are returned

View File

@ -47,7 +47,7 @@ module Risc
compiler = Risc::MethodCompiler.create_method(:Object,:__init__ , compiler = Risc::MethodCompiler.create_method(:Object,:__init__ ,
Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({})) Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({}))
builder = Risc::Builder.new(compiler) builder = Risc::Builder.new(compiler)
builder.build_and_add do builder.build do
space << Parfait.object_space space << Parfait.object_space
message << space[:first_message] message << space[:first_message]
next_message << message[:next_message] next_message << message[:next_message]
@ -57,7 +57,7 @@ module Risc
risc = Mom::MessageSetup.new(Parfait.object_space.get_main).build_with( builder ) risc = Mom::MessageSetup.new(Parfait.object_space.get_main).build_with( builder )
compiler.add_code(risc) compiler.add_code(risc)
builder.build_and_add do builder.build do
message << message[:next_message] message << message[:next_message]
message[:receiver] << space message[:receiver] << space
end end

View File

@ -170,5 +170,15 @@ module Risc
def reduce_int( source , register ) def reduce_int( source , register )
add_slot_to_reg( source + "int -> fix" , register , Parfait::Integer.integer_index , register) add_slot_to_reg( source + "int -> fix" , register , Parfait::Integer.integer_index , register)
end 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
end end

View File

@ -20,9 +20,22 @@ module Risc
SlotToReg, RegToSlot, SlotToReg, SlotToReg, SlotToReg, SlotToReg, RegToSlot, SlotToReg, SlotToReg, SlotToReg,
SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot, SlotToReg, RegToSlot, LoadConstant, SlotToReg, RegToSlot,
SlotToReg, LoadConstant, FunctionCall, Label, SlotToReg, SlotToReg, LoadConstant, FunctionCall, Label, SlotToReg,
SlotToReg, SlotToReg, SlotToReg, Label, LoadConstant, SlotToReg, SlotToReg, SlotToReg, SlotToReg, Label,
SlotToReg, OperatorInstruction, IsZero, Label, Transfer, LoadConstant, SlotToReg, OperatorInstruction, IsZero, SlotToReg,
Syscall, NilClass] 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 #assert_equal 1 , get_return
end end

View File

@ -6,8 +6,7 @@ module Risc
def setup def setup
Risc.machine.boot Risc.machine.boot
init = Parfait.object_space.get_init init = Parfait.object_space.get_init
compiler = Risc::MethodCompiler.new( init ) @builder = Risc::MethodCompiler.new( init ).builder
@builder = Builder.new(compiler)
end end
def test_has_build def test_has_build
assert @builder.respond_to?(:build) assert @builder.respond_to?(:build)