add the ! syntax to create variables in builder, fix #8

now a variable has to be created before being used
thus it is save to develop contracts where a certain name
must exist in the scope
Maybe the syntax starts getting a bit weird, but at least the ! is a common symbol in ruby
This commit is contained in:
Torsten Ruger 2018-08-14 19:39:46 +03:00
parent 0bf008b351
commit 37461a1727
9 changed files with 68 additions and 60 deletions

View File

@ -36,16 +36,16 @@ module Mom
def build_with(builder) def build_with(builder)
case from = method_source case from = method_source
when Parfait::CallableMethod when Parfait::CallableMethod
builder.build { callable << from } builder.build { callable! << from }
when Parfait::CacheEntry when Parfait::CacheEntry
builder.build do builder.build do
cache_entry << from cache_entry! << from
callable << cache_entry[:cached_method] callable! << cache_entry[:cached_method]
end end
when Integer when Integer
builder.build do builder.build do
arguments << message[:arguments] arguments! << message[:arguments]
callable << arguments[ from ] callable! << arguments[ from ]
end end
else else
raise "unknown source #{method_source.class}:#{method_source}" raise "unknown source #{method_source.class}:#{method_source}"
@ -64,11 +64,11 @@ module Mom
# set the method into the message # set the method into the message
def build_message_data( builder ) def build_message_data( builder )
builder.build do builder.build do
space << Parfait.object_space space! << Parfait.object_space
next_message << space[:next_message] next_message! << space[:next_message]
#FIXME in a multithreaded future this should be done using lock free compare and swap. #FIXME in a multithreaded future this should be done using lock free compare and swap.
next_message_reg << next_message[:next_message] next_message_reg! << next_message[:next_message]
space[:next_message] << next_message_reg space[:next_message] << next_message_reg
message[:next_message] << next_message message[:next_message] << next_message

View File

@ -37,20 +37,20 @@ module Mom
cache_entry_ = @cache_entry cache_entry_ = @cache_entry
builder = compiler.code_builder(self) builder = compiler.code_builder(self)
builder.build do builder.build do
word << name_ word! << name_
cache_entry << cache_entry_ cache_entry! << cache_entry_
type << cache_entry[:cached_type] type! << cache_entry[:cached_type]
callable_method << type[:methods] callable_method! << type[:methods]
add_code while_start_label add_code while_start_label
space << Parfait.object_space space! << Parfait.object_space
space << space[:nil_object] space << space[:nil_object]
space - callable_method space - callable_method
if_zero exit_label if_zero exit_label
name << callable_method[:name] name! << callable_method[:name]
name - word name - word
if_zero ok_label if_zero ok_label

View File

@ -23,17 +23,17 @@ module Mom
compiler.reset_regs compiler.reset_regs
builder = compiler.code_builder(self) builder = compiler.code_builder(self)
builder.build do builder.build do
object << message[:return_value] object! << message[:return_value]
caller_reg << message[:caller] caller_reg! << message[:caller]
caller_reg[:return_value] << object caller_reg[:return_value] << object
space << Parfait.object_space space! << Parfait.object_space
next_message << space[:next_message] next_message! << space[:next_message]
message[:next_message] << next_message message[:next_message] << next_message
space[:next_message] << message space[:next_message] << message
end end
compiler.reset_regs compiler.reset_regs
builder.build do builder.build do
return_address << message[:return_address] return_address! << message[:return_address]
return_address << return_address[ Parfait::Integer.integer_index] return_address << return_address[ Parfait::Integer.integer_index]
message << message[:caller] message << message[:caller]
return_address.function_return return_address.function_return

View File

@ -28,17 +28,21 @@ module Risc
# make the magic: convert incoming names into registers that have the # make the magic: convert incoming names into registers that have the
# type set according to the name (using resolve_type) # type set according to the name (using resolve_type)
# anmes are stored, so subsequent calls use the same register # anmes are stored, so subsequent calls use the same register
def method_missing(*args) def method_missing(name , *args)
super if args.length != 1 super if args.length != 0
name = args[0] name = name.to_s
return @names[name] if @names.has_key?(name) return @names[name] if @names.has_key?(name)
if name == :message if name == "message"
reg = Risc.message_reg reg = Risc.message_reg
reg.builder = self reg.builder = self
elsif name.to_s.index("label") return reg
end
if name.index("label")
reg = Risc.label( @source , "#{name}_#{object_id}") reg = Risc.label( @source , "#{name}_#{object_id}")
@source_used = true @source_used = true
else else
raise "Must create (with !) before using #{name}" unless name[-1] == "!"
name = name[0 ... -1]
type = infer_type(name ) type = infer_type(name )
reg = @compiler.use_reg( type.object_class.name ) reg = @compiler.use_reg( type.object_class.name )
reg.builder = self reg.builder = self
@ -90,6 +94,7 @@ module Risc
# but since the names in the builder are not variables, we need this method # 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 # as it says, swap the two names around. Names must exist
def swap_names(left , right) def swap_names(left , right)
left , right = left.to_s , right.to_s
l = @names[left] l = @names[left]
r = @names[right] r = @names[right]
raise "No such name #{left}" unless l raise "No such name #{left}" unless l
@ -127,9 +132,9 @@ module Risc
to.builder = self # esecially div10 comes in without having used builder to.builder = self # esecially div10 comes in without having used builder
from.builder = self # not named regs, different regs ==> silent errors from.builder = self # not named regs, different regs ==> silent errors
build do build do
space << Parfait.object_space space! << Parfait.object_space
to << space[:next_integer] to << space[:next_integer]
integer_tmp << to[:next_integer] integer_tmp! << to[:next_integer]
space[:next_integer] << integer_tmp space[:next_integer] << integer_tmp
to[Parfait::Integer.integer_index] << from to[Parfait::Integer.integer_index] << from
end end

View File

@ -14,9 +14,9 @@ module Risc
def div4(context) def div4(context)
compiler = compiler_for(:Integer,:div4 ,{}) compiler = compiler_for(:Integer,:div4 ,{})
compiler.compiler_builder(compiler.source).build do compiler.compiler_builder(compiler.source).build do
integer << message[:receiver] integer! << message[:receiver]
integer.reduce_int integer.reduce_int
integer_reg << 2 integer_reg! << 2
integer.op :>> , integer_reg integer.op :>> , integer_reg
add_new_int("div4", integer , integer_reg) add_new_int("div4", integer , integer_reg)
message[:return_value] << integer_reg message[:return_value] << integer_reg
@ -52,8 +52,8 @@ module Risc
compiler = compiler_for(:Integer, operator ,{other: :Integer}) compiler = compiler_for(:Integer, operator ,{other: :Integer})
builder = compiler.compiler_builder(compiler.source) builder = compiler.compiler_builder(compiler.source)
builder.build do builder.build do
integer << message[:receiver] integer! << message[:receiver]
integer_reg << message[:arguments] integer_reg! << message[:arguments]
integer_reg << integer_reg[ 1] integer_reg << integer_reg[ 1]
integer.reduce_int integer.reduce_int
integer_reg.reduce_int integer_reg.reduce_int
@ -61,7 +61,7 @@ module Risc
integer.op :- , integer_reg integer.op :- , integer_reg
if_minus false_label if_minus false_label
if_zero( false_label ) if operator.to_s.length == 1 if_zero( false_label ) if operator.to_s.length == 1
object << Parfait.object_space.true_object object! << Parfait.object_space.true_object
branch merge_label branch merge_label
add_code false_label add_code false_label
object << Parfait.object_space.false_object object << Parfait.object_space.false_object
@ -89,8 +89,8 @@ module Risc
compiler = compiler_for(:Integer, op_sym ,{other: :Integer}) compiler = compiler_for(:Integer, op_sym ,{other: :Integer})
builder = compiler.compiler_builder(compiler.source) builder = compiler.compiler_builder(compiler.source)
builder.build do builder.build do
integer << message[:receiver] integer! << message[:receiver]
integer_reg << message[:arguments] integer_reg! << message[:arguments]
integer_reg << integer_reg[ 1] integer_reg << integer_reg[ 1]
integer.reduce_int integer.reduce_int
integer_reg.reduce_int integer_reg.reduce_int

View File

@ -9,9 +9,9 @@ module Risc
def get_internal_word( context ) def get_internal_word( context )
compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer}) compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer})
compiler.compiler_builder(compiler.source).build do compiler.compiler_builder(compiler.source).build do
object << message[:receiver] object! << message[:receiver]
integer << message[:arguments] integer! << message[:arguments]
integer << integer_reg[1] integer << integer[1]
integer.reduce_int integer.reduce_int
object << object[integer] object << object[integer]
message[:return_value] << object message[:return_value] << object
@ -25,10 +25,10 @@ module Risc
def set_internal_word( context ) def set_internal_word( context )
compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, :value => :Object} ) compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, :value => :Object} )
compiler.compiler_builder(compiler.source).build do compiler.compiler_builder(compiler.source).build do
object << message[:receiver] object! << message[:receiver]
integer << message[:arguments] integer! << message[:arguments]
object_reg << integer[ 2] object_reg! << integer[ 2]
integer << integer[ 1] integer << integer[1]
integer.reduce_int integer.reduce_int
object[integer] << object_reg object[integer] << object_reg
message[:return_value] << object_reg message[:return_value] << object_reg
@ -56,9 +56,9 @@ module Risc
Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({})) Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({}))
builder = compiler.compiler_builder(compiler.source) builder = compiler.compiler_builder(compiler.source)
builder.build do builder.build do
space << Parfait.object_space space! << Parfait.object_space
message << space[:next_message] message << space[:next_message]
next_message << message[:next_message] next_message! << message[:next_message]
space[:next_message] << next_message space[:next_message] << next_message
end end
@ -128,7 +128,7 @@ module Risc
r8 = RegisterValue.new( :r8 , :Message) r8 = RegisterValue.new( :r8 , :Message)
int = builder.compiler.use_reg(:Integer) int = builder.compiler.use_reg(:Integer)
builder.build do builder.build do
integer_reg << message integer_reg! << message
message << r8 message << r8
add_new_int( "_restore_message", integer_reg , int ) add_new_int( "_restore_message", integer_reg , int )
message[:return_value] << int message[:return_value] << int

View File

@ -28,8 +28,8 @@ module Risc
def get_internal_byte( context) def get_internal_byte( context)
compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer}) compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer})
compiler.compiler_builder(compiler.source).build do compiler.compiler_builder(compiler.source).build do
object << message[:receiver] object! << message[:receiver]
integer << message[:arguments] integer! << message[:arguments]
integer << integer[1] integer << integer[1]
integer.reduce_int integer.reduce_int
object <= object[integer] object <= object[integer]
@ -46,11 +46,11 @@ module Risc
def set_internal_byte( context ) def set_internal_byte( context )
compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , :value => :Integer} ) compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , :value => :Integer} )
compiler.compiler_builder(compiler.source).build do compiler.compiler_builder(compiler.source).build do
word << message[:receiver] word! << message[:receiver]
integer << message[:arguments] integer! << message[:arguments]
integer << integer[1] integer << integer[1]
integer_reg << message[:arguments] integer_reg! << message[:arguments]
integer_obj << integer_reg[2] integer_obj! << integer_reg[2]
integer_reg << integer_reg[2] integer_reg << integer_reg[2]
integer.reduce_int integer.reduce_int
integer_reg.reduce_int integer_reg.reduce_int

View File

@ -17,12 +17,15 @@ module Risc
assert_nil @builder.built assert_nil @builder.built
end end
def test_alloc_space def test_alloc_space
reg = @builder.space reg = @builder.space!
assert_equal RegisterValue , reg.class assert_equal RegisterValue , reg.class
assert_equal :Space , reg.type.class_name assert_equal :Space , reg.type.class_name
end end
def test_not_alloc_space
assert_raises {@builder.space}
end
def test_next_message def test_next_message
reg = @builder.next_message reg = @builder.next_message!
assert_equal :r1 , reg.symbol assert_equal :r1 , reg.symbol
assert_equal :Message , reg.type.class_name assert_equal :Message , reg.type.class_name
end end
@ -33,31 +36,31 @@ module Risc
end end
def test_returns_built def test_returns_built
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ space << r1 } built = @builder.build{ space! << r1 }
assert_equal Transfer , built.class assert_equal Transfer , built.class
end end
def test_returns_two def test_returns_two
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ space << r1 ; space << r1} built = @builder.build{ space! << r1 ; space << r1}
assert_equal Transfer , built.next.class assert_equal Transfer , built.next.class
end end
def test_returns_slot def test_returns_slot
r2 = RegisterValue.new(:r2 , :Message) r2 = RegisterValue.new(:r2 , :Message)
r2.builder = @builder r2.builder = @builder
built = @builder.build{ r2 << space[:next_message] } built = @builder.build{ r2 << space![:next_message] }
assert_equal SlotToReg , built.class assert_equal SlotToReg , built.class
assert_equal :r1 , built.array.symbol assert_equal :r1 , built.array.symbol
end end
def test_returns_slot_reverse def test_returns_slot_reverse
r2 = RegisterValue.new(:r2 , :Message) r2 = RegisterValue.new(:r2 , :Message)
r2.builder = @builder r2.builder = @builder
built = @builder.build{ r2 << space[:next_message] } built = @builder.build{ r2 << space![:next_message] }
assert_equal SlotToReg , built.class assert_equal SlotToReg , built.class
assert_equal :r1 , built.array.symbol assert_equal :r1 , built.array.symbol
end end
def test_reuses_names def test_reuses_names
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ space << r1 ; space << r1} built = @builder.build{ space! << r1 ; space << r1}
assert_equal built.to.symbol , built.next.to.symbol assert_equal built.to.symbol , built.next.to.symbol
end end
def test_uses_message_as_message def test_uses_message_as_message
@ -92,7 +95,7 @@ module Risc
assert_equal @label , ret.label assert_equal @label , ret.label
end end
def test_minus def test_minus
op = @builder.build {space - callable_method} op = @builder.build {space! - callable_method!}
assert_equal OperatorInstruction , op.class assert_equal OperatorInstruction , op.class
assert_equal :- , op.operator assert_equal :- , op.operator
assert_equal :Space , op.left.type.class_name assert_equal :Space , op.left.type.class_name

View File

@ -12,17 +12,17 @@ module Risc
end end
def test_inserts_built def test_inserts_built
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)
@builder.build{ space << r1 } @builder.build{ space! << r1 }
assert_equal Transfer , @compiler.risc_instructions.next.class assert_equal Transfer , @compiler.risc_instructions.next.class
assert_equal RegisterValue , @builder.space.class assert_equal RegisterValue , @builder.space.class
end end
def test_loads def test_loads
@builder.build{ space << Parfait.object_space } @builder.build{ space! << Parfait.object_space }
assert_equal LoadConstant , @compiler.risc_instructions.next.class assert_equal LoadConstant , @compiler.risc_instructions.next.class
assert_equal RegisterValue , @builder.space.class assert_equal RegisterValue , @builder.space.class
end end
def test_two def test_two
@builder.build{ space << Parfait.object_space ; integer << 1} @builder.build{ space! << Parfait.object_space ; integer! << 1}
assert_equal LoadConstant , @compiler.risc_instructions.next.class assert_equal LoadConstant , @compiler.risc_instructions.next.class
assert_equal LoadData , @compiler.risc_instructions.next(2).class assert_equal LoadData , @compiler.risc_instructions.next(2).class
end end