create a load on the compiler
thus removing the need for << with objects on RegisterValue
This commit is contained in:
parent
95f3eec043
commit
64d860b2bf
@ -90,18 +90,16 @@ module Risc
|
|||||||
copied
|
copied
|
||||||
end
|
end
|
||||||
|
|
||||||
# releasing a register (accuired by use_reg) makes it available for use again
|
# Load a constant, meaning create a LoadConstant instruction for the constant
|
||||||
# thus avoiding possibly using too many registers
|
# add the instruction to the code and return the register_value that was created
|
||||||
def release_reg( reg )
|
# for further use
|
||||||
last = @allocator.pop
|
def load_object( object )
|
||||||
raise "released register in wrong order, expect #{last} but was #{reg}" if reg != last
|
raise "must be Parfait, not #{object.class}" unless object.is_a?(Parfait::Object)
|
||||||
end
|
ins = Risc.load_constant("load to #{object.type}" , object)
|
||||||
|
add_code ins
|
||||||
# reset the registers to be used. Start at r4 for next usage.
|
# todo for constants (not objects)
|
||||||
# Every statement starts with this, meaning each statement may use all registers, but none
|
# add_constant(right) if compiler
|
||||||
# get saved. Statements have affect on objects.
|
ins.register
|
||||||
def reset_regs
|
|
||||||
@allocator.clear_regs
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Build with builder (see there), adding the created instructions
|
# Build with builder (see there), adding the created instructions
|
||||||
|
@ -14,10 +14,10 @@ module Risc
|
|||||||
# or r-vlalue respectively.
|
# or r-vlalue respectively.
|
||||||
|
|
||||||
class RegisterSlot
|
class RegisterSlot
|
||||||
attr_reader :register , :index , :builder
|
attr_reader :register , :index , :compiler
|
||||||
|
|
||||||
def initialize(register, index , builder)
|
def initialize(register, index , compiler)
|
||||||
@register , @index , @builder = register , index , builder
|
@register , @index , @compiler = register , index , compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# fullfil the objects purpose by creating a RegToSlot instruction from
|
# fullfil the objects purpose by creating a RegToSlot instruction from
|
||||||
@ -25,7 +25,7 @@ module Risc
|
|||||||
def <<( reg )
|
def <<( reg )
|
||||||
raise "not reg #{reg}" unless reg.is_a?(RegisterValue)
|
raise "not reg #{reg}" unless reg.is_a?(RegisterValue)
|
||||||
reg_to_slot = Risc.reg_to_slot("#{reg.class_name} -> #{register.class_name}[#{index}]" , reg , register, index)
|
reg_to_slot = Risc.reg_to_slot("#{reg.class_name} -> #{register.class_name}[#{index}]" , reg , register, index)
|
||||||
builder.add_code(reg_to_slot) if builder
|
compiler.add_code(reg_to_slot) if compiler
|
||||||
reg_to_slot
|
reg_to_slot
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ module Risc
|
|||||||
def <=( reg )
|
def <=( reg )
|
||||||
raise "not reg #{reg}" unless reg.is_a?(RegisterValue)
|
raise "not reg #{reg}" unless reg.is_a?(RegisterValue)
|
||||||
reg_to_byte = Risc.reg_to_byte("#{reg.class_name} -> #{register.class_name}[#{index}]" , reg , register, index)
|
reg_to_byte = Risc.reg_to_byte("#{reg.class_name} -> #{register.class_name}[#{index}]" , reg , register, index)
|
||||||
builder.add_code(reg_to_byte) if builder
|
compiler.add_code(reg_to_byte) if compiler
|
||||||
reg_to_byte
|
reg_to_byte
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5,13 +5,13 @@ module Risc
|
|||||||
# The type is always known, and sometimes the value too
|
# The type is always known, and sometimes the value too
|
||||||
# Or something about the value, like some instances types
|
# Or something about the value, like some instances types
|
||||||
#
|
#
|
||||||
# When participating in the builder dsl, a builder may be set to get the
|
# When participating in the compiler dsl, a compiler may be set to get the
|
||||||
# results of dsl operations (like <<) back to the builder
|
# results of dsl operations (like <<) back to the compiler
|
||||||
class RegisterValue
|
class RegisterValue
|
||||||
|
|
||||||
attr_reader :symbol , :type , :extra
|
attr_reader :symbol , :type , :extra
|
||||||
|
|
||||||
attr_reader :builder
|
attr_reader :compiler
|
||||||
|
|
||||||
# The first arg is a symbol :r0 - :r12
|
# The first arg is a symbol :r0 - :r12
|
||||||
# Second arg is the type, which may be given as the symbol of the class name
|
# Second arg is the type, which may be given as the symbol of the class name
|
||||||
@ -34,11 +34,11 @@ module Risc
|
|||||||
@type.class_name
|
@type.class_name
|
||||||
end
|
end
|
||||||
|
|
||||||
# allows to set the builder, which is mainly done by the builder
|
# allows to set the compiler, which is mainly done by the compiler
|
||||||
# but sometimes, eg in exit, one nneds to create the reg by hand and set
|
# but sometimes, eg in exit, one nneds to create the reg by hand and set
|
||||||
# return the RegisterValue for chaining in assignment
|
# return the RegisterValue for chaining in assignment
|
||||||
def set_builder( builder )
|
def set_compiler( compiler )
|
||||||
@builder = builder
|
@compiler = compiler
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,10 +64,10 @@ module Risc
|
|||||||
type.type_at(index)
|
type.type_at(index)
|
||||||
end
|
end
|
||||||
|
|
||||||
# reduce integer to fixnum and add instruction if builder is used
|
# reduce integer to fixnum and add instruction if compiler is used
|
||||||
def reduce_int
|
def reduce_int
|
||||||
reduce = Risc::SlotToReg.new( "int -> fix" , self , Parfait::Integer.integer_index , self)
|
reduce = Risc::SlotToReg.new( "int -> fix" , self , Parfait::Integer.integer_index , self)
|
||||||
builder.add_code(reduce) if builder
|
compiler.add_code(reduce) if compiler
|
||||||
reduce
|
reduce
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -136,25 +136,19 @@ module Risc
|
|||||||
# - an RegisterSlot, resulting in an SlotToReg
|
# - an RegisterSlot, resulting in an SlotToReg
|
||||||
def <<( right )
|
def <<( right )
|
||||||
case right
|
case right
|
||||||
when Symbol
|
|
||||||
ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
|
|
||||||
when Parfait::Object
|
|
||||||
ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
|
|
||||||
builder.compiler.add_constant(right) if builder
|
|
||||||
when Label
|
when Label
|
||||||
ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
|
ins = Risc::LoadConstant.new("#{right.class} to #{self.type}" , right , self)
|
||||||
builder.compiler.add_constant(right.address) if builder
|
compiler.compiler.add_constant(right.address) if compiler
|
||||||
when ::Integer
|
when ::Integer
|
||||||
ins = Risc.load_data("#{right.class} to #{self.type}" , right , self)
|
ins = Risc.load_data("#{right.class} to #{self.type}" , right , self)
|
||||||
when RegisterValue
|
when RegisterValue
|
||||||
ins = Risc.transfer("#{right.type} to #{self.type}" , right , self)
|
ins = Risc.transfer("#{right.type} to #{self.type}" , right , self)
|
||||||
when RegisterSlot
|
when RegisterSlot
|
||||||
puts right.to_s
|
|
||||||
ins = Risc::SlotToReg.new("#{right.register.type}[#{right.index}] -> #{self.type}" , right.register , right.index , self)
|
ins = Risc::SlotToReg.new("#{right.register.type}[#{right.index}] -> #{self.type}" , right.register , right.index , self)
|
||||||
else
|
else
|
||||||
raise "not implemented for #{right.class}:#{right}"
|
raise "not implemented for #{right.class}:#{right}"
|
||||||
end
|
end
|
||||||
builder.add_code(ins) if builder
|
compiler.add_code(ins) if compiler
|
||||||
return ins
|
return ins
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -163,14 +157,14 @@ module Risc
|
|||||||
def <=( right )
|
def <=( right )
|
||||||
raise "not implemented for #{right.class}:#{right}" unless right.is_a?( RegisterSlot )
|
raise "not implemented for #{right.class}:#{right}" unless right.is_a?( RegisterSlot )
|
||||||
ins = Risc.byte_to_reg("#{right.register.type}[#{right.index}] -> #{self.type}" , right.register , right.index , self)
|
ins = Risc.byte_to_reg("#{right.register.type}[#{right.index}] -> #{self.type}" , right.register , right.index , self)
|
||||||
builder.add_code(ins) if builder
|
compiler.add_code(ins) if compiler
|
||||||
return ins
|
return ins
|
||||||
end
|
end
|
||||||
|
|
||||||
def -( right )
|
def -( right )
|
||||||
raise "operators only on registers, not #{right.class}" unless right.is_a? RegisterValue
|
raise "operators only on registers, not #{right.class}" unless right.is_a? RegisterValue
|
||||||
op = Risc.op("#{self.type} - #{right.type}", :- , self , right )
|
op = Risc.op("#{self.type} - #{right.type}", :- , self , right )
|
||||||
builder.add_code(op) if builder
|
compiler.add_code(op) if compiler
|
||||||
op
|
op
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -178,7 +172,7 @@ module Risc
|
|||||||
# doesn't read quite as smoothly as one would like, but better than the compiler version
|
# doesn't read quite as smoothly as one would like, but better than the compiler version
|
||||||
def op( operator , right)
|
def op( operator , right)
|
||||||
ret = Risc.op( "operator #{operator}" , operator , self , right)
|
ret = Risc.op( "operator #{operator}" , operator , self , right)
|
||||||
builder.add_code(ret) if builder
|
compiler.add_code(ret) if compiler
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -186,7 +180,7 @@ module Risc
|
|||||||
# The RegisterSlot then gets used in a RegToSlot or SlotToReg, where
|
# The RegisterSlot then gets used in a RegToSlot or SlotToReg, where
|
||||||
# the values are unpacked to call Risc.reg_to_slot or Risc.slot_to_reg
|
# the values are unpacked to call Risc.reg_to_slot or Risc.slot_to_reg
|
||||||
def []( index )
|
def []( index )
|
||||||
RegisterSlot.new( self , index , builder)
|
RegisterSlot.new( self , index , compiler)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
module Risc
|
module Risc
|
||||||
class FakeCallableCompiler < CallableCompiler
|
|
||||||
def initialize(a,c)
|
|
||||||
super(a,c)
|
|
||||||
end
|
|
||||||
def source_name
|
|
||||||
"luke"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class TestCallableCompiler < MiniTest::Test
|
class TestCallableCompiler < MiniTest::Test
|
||||||
def setup
|
def setup
|
||||||
Parfait.boot!({})
|
Parfait.boot!({})
|
||||||
@ -29,28 +21,15 @@ module Risc
|
|||||||
def test_const
|
def test_const
|
||||||
assert_equal Array , @compiler.constants.class
|
assert_equal Array , @compiler.constants.class
|
||||||
end
|
end
|
||||||
|
def test_load_class
|
||||||
|
object = @compiler.load_object(Parfait.object_space)
|
||||||
|
assert_equal RegisterValue , object.class
|
||||||
|
assert object.is_object?
|
||||||
end
|
end
|
||||||
class TestFakeCallableCompiler < MiniTest::Test
|
def test_load_code
|
||||||
def setup
|
object = @compiler.load_object(Parfait.object_space)
|
||||||
Parfait.boot!({})
|
assert_equal LoadConstant , @compiler.current.class
|
||||||
label = SlotMachine::Label.new("hi","ho")
|
assert_equal Parfait::Space , @compiler.current.constant.class
|
||||||
@compiler = FakeCallableCompiler.new(FakeCallable.new , label)
|
|
||||||
end
|
|
||||||
def test_ok
|
|
||||||
assert @compiler
|
|
||||||
end
|
|
||||||
def test_current
|
|
||||||
assert @compiler.current
|
|
||||||
end
|
|
||||||
def test_current_label
|
|
||||||
assert_equal Label , @compiler.current.class
|
|
||||||
assert_equal "ho" , @compiler.current.name
|
|
||||||
end
|
|
||||||
def test_slot
|
|
||||||
assert @compiler.risc_instructions
|
|
||||||
end
|
|
||||||
def test_const
|
|
||||||
assert_equal Array , @compiler.constants.class
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -17,14 +17,6 @@ module Risc
|
|||||||
def test_r0
|
def test_r0
|
||||||
assert_equal :message , @r0.symbol
|
assert_equal :message , @r0.symbol
|
||||||
end
|
end
|
||||||
def test_load_space
|
|
||||||
move = @r0 << Parfait.object_space
|
|
||||||
assert_equal LoadConstant , move.class
|
|
||||||
end
|
|
||||||
def test_load_symbol
|
|
||||||
move = @r1 << :puts
|
|
||||||
assert_equal LoadConstant , move.class
|
|
||||||
end
|
|
||||||
def test_load_label
|
def test_load_label
|
||||||
label = Risc::Label.new("HI","ho" , FakeAddress.new(0))
|
label = Risc::Label.new("HI","ho" , FakeAddress.new(0))
|
||||||
move = @r1 << label
|
move = @r1 << label
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
require_relative "../helper"
|
require_relative "../helper"
|
||||||
|
|
||||||
class FakeBuilder
|
class SuperFakeCompiler
|
||||||
attr_reader :built
|
attr_reader :code
|
||||||
def add_code(ins)
|
def add_code(ins)
|
||||||
@built = ins
|
@code = ins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
module Risc
|
module Risc
|
||||||
@ -24,14 +24,6 @@ module Risc
|
|||||||
def test_r0
|
def test_r0
|
||||||
assert_equal :message , @r0.symbol
|
assert_equal :message , @r0.symbol
|
||||||
end
|
end
|
||||||
def test_load_space
|
|
||||||
move = @r0 << Parfait.object_space
|
|
||||||
assert_equal LoadConstant , move.class
|
|
||||||
end
|
|
||||||
def test_load_symbol
|
|
||||||
move = @r1 << :puts
|
|
||||||
assert_equal LoadConstant , move.class
|
|
||||||
end
|
|
||||||
def test_load_label
|
def test_load_label
|
||||||
label = Risc::Label.new("HI","ho" , FakeAddress.new(0))
|
label = Risc::Label.new("HI","ho" , FakeAddress.new(0))
|
||||||
move = @r1 << label
|
move = @r1 << label
|
||||||
@ -41,16 +33,16 @@ module Risc
|
|||||||
transfer = @r0 << @r1
|
transfer = @r0 << @r1
|
||||||
assert_equal Transfer , transfer.class
|
assert_equal Transfer , transfer.class
|
||||||
end
|
end
|
||||||
def test_set_builder
|
def test_set_compiler
|
||||||
reg = @r0.set_builder(FakeBuilder.new)
|
reg = @r0.set_compiler(SuperFakeCompiler.new)
|
||||||
assert_equal RegisterValue , reg.class
|
assert_equal RegisterValue , reg.class
|
||||||
assert reg.builder
|
assert reg.compiler
|
||||||
end
|
end
|
||||||
def test_calls_builder
|
def test_calls_compiler
|
||||||
builder = FakeBuilder.new
|
compiler = SuperFakeCompiler.new
|
||||||
@r0.set_builder( builder )
|
@r0.set_compiler( compiler )
|
||||||
@r0 << @r1
|
@r0 << @r1
|
||||||
assert_equal Transfer , builder.built.class
|
assert_equal Transfer , compiler.code.class
|
||||||
end
|
end
|
||||||
def test_index_op
|
def test_index_op
|
||||||
message = @r0[:next_message]
|
message = @r0[:next_message]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
require_relative "helper"
|
require_relative "helper"
|
||||||
module SlotMachine
|
module SlotMachine
|
||||||
|
# need to derive, to overwrite source_name
|
||||||
class FakeCallableCompiler < CallableCompiler
|
class FakeCallableCompiler < CallableCompiler
|
||||||
def source_name
|
def source_name
|
||||||
"luke"
|
"luke"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user