remove the code_builder

this is core of #11
rename compiler_builder to just builder
and change all builder uses to use that
some test change as code is not returned anymore
This commit is contained in:
Torsten Ruger 2018-08-19 13:16:07 +03:00
parent b294208025
commit 57dc6c45bb
10 changed files with 44 additions and 93 deletions

View File

@ -2,14 +2,7 @@ module Risc
# A Builder is used to generate code, either by using it's api, or dsl # A Builder is used to generate code, either by using it's api, or dsl
# #
# There are two subclasses of Builder, depending of what one wants to do with the # The code is added to the method_compiler.
# generated code.
#
# CompilerBuilder: The code is added to the method_compiler.
# This is used to generate the builtin methods.
#
# CodeBuilder: The code can be stored up and returned.
# This is used in Mom::to_risc methods
# #
class Builder class Builder
@ -19,6 +12,7 @@ module Risc
# second arg determines weather instructions are added (default true) # second arg determines weather instructions are added (default true)
# call build with a block to build # call build with a block to build
def initialize(compiler, for_source) def initialize(compiler, for_source)
raise "no compiler" unless compiler
@compiler = compiler @compiler = compiler
@source = for_source @source = for_source
@source_used = false @source_used = false
@ -119,16 +113,16 @@ module Risc
# space << Parfait.object_space # load constant # space << Parfait.object_space # load constant
# message[:receiver] << space #make current message (r0) receiver the space # message[:receiver] << space #make current message (r0) receiver the space
# #
# build result is available as built, but also gets added to compiler, if the # build result is added to compiler directly
# builder is created with default args
# #
def build(&block) def build(&block)
instance_eval(&block) instance_eval(&block)
@built
end end
# add code straight to the compiler
def add_code(ins) def add_code(ins)
raise "Must be implemented in subclass #{self}" @compiler.add_code(ins)
return ins
end end
# move a machine int from register "from" to a Parfait::Integer in register "to" # move a machine int from register "from" to a Parfait::Integer in register "to"
@ -146,39 +140,4 @@ module Risc
end end
end end
class CodeBuilder < Builder
attr_reader :built
def initialize(compiler, for_source)
super
@built = nil
end
def build(&block)
super
@built
end
# CodeBuilder stores the code.
# The code can be access through the @built instance, and is returned
# from build method
def add_code(ins)
if(@built)
@built << ins
else
@built = ins
end
end
end
# A CompilerBuilder adds the generated code to the MethodCompiler.
#
class CompilerBuilder < Builder
# add code straight to the compiler
def add_code(ins)
return @compiler.add_code(ins)
end
end
end end

View File

@ -13,7 +13,7 @@ module Risc
# return new int with result # return new int with result
def div4(context) def div4(context)
compiler = compiler_for(:Integer,:div4 ,{}) compiler = compiler_for(:Integer,:div4 ,{})
compiler.compiler_builder(compiler.source).build do compiler.builder(compiler.source).build do
integer! << message[:receiver] integer! << message[:receiver]
integer.reduce_int integer.reduce_int
integer_reg! << 2 integer_reg! << 2
@ -50,7 +50,7 @@ module Risc
# - return # - return
def comparison( operator ) def comparison( operator )
compiler = compiler_for(:Integer, operator ,{other: :Integer}) compiler = compiler_for(:Integer, operator ,{other: :Integer})
builder = compiler.compiler_builder(compiler.source) builder = compiler.builder(compiler.source)
builder.build do builder.build do
integer! << message[:receiver] integer! << message[:receiver]
integer_reg! << message[:arguments] integer_reg! << message[:arguments]
@ -87,7 +87,7 @@ module Risc
# - returns the new int # - returns the new int
def operator_method( op_sym ) def operator_method( op_sym )
compiler = compiler_for(:Integer, op_sym ,{other: :Integer}) compiler = compiler_for(:Integer, op_sym ,{other: :Integer})
builder = compiler.compiler_builder(compiler.source) builder = compiler.builder(compiler.source)
builder.build do builder.build do
integer! << message[:receiver] integer! << message[:receiver]
integer_reg! << message[:arguments] integer_reg! << message[:arguments]
@ -113,7 +113,7 @@ module Risc
def div10( context ) def div10( context )
s = "div_10 " s = "div_10 "
compiler = compiler_for(:Integer,:div10 ,{}) compiler = compiler_for(:Integer,:div10 ,{})
builder = compiler.compiler_builder(compiler.source) builder = compiler.builder(compiler.source)
builder.build do builder.build do
integer_self! << message[:receiver] integer_self! << message[:receiver]
integer_self.reduce_int integer_self.reduce_int

View File

@ -8,7 +8,7 @@ module Risc
# return is stored in return_value # return is stored in return_value
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.builder(compiler.source).build do
object! << message[:receiver] object! << message[:receiver]
integer! << message[:arguments] integer! << message[:arguments]
integer << integer[1] integer << integer[1]
@ -24,7 +24,7 @@ module Risc
# return the value passed in # return the value passed in
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.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]
@ -41,7 +41,7 @@ module Risc
# Even if it's just this one, sys_exit (later raise) # Even if it's just this one, sys_exit (later raise)
def _method_missing( context ) def _method_missing( context )
compiler = compiler_for(:Object,:method_missing ,{}) compiler = compiler_for(:Object,:method_missing ,{})
emit_syscall( compiler.compiler_builder(compiler.source) , :exit ) emit_syscall( compiler.builder(compiler.source) , :exit )
return compiler return compiler
end end
@ -54,7 +54,7 @@ module Risc
def __init__( context ) def __init__( context )
compiler = MethodCompiler.compiler_for_class(:Object,:__init__ , compiler = MethodCompiler.compiler_for_class(:Object,:__init__ ,
Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({})) Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({}))
builder = compiler.compiler_builder(compiler.source) builder = 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]
@ -98,7 +98,7 @@ module Risc
# mainly calls exit_sequence # mainly calls exit_sequence
def exit( context ) def exit( context )
compiler = compiler_for(:Object,:exit ,{}) compiler = compiler_for(:Object,:exit ,{})
builder = compiler.compiler_builder(compiler.source) builder = compiler.builder(compiler.source)
exit_sequence(builder) exit_sequence(builder)
return compiler return compiler
end end

View File

@ -12,7 +12,7 @@ module Risc
# - emit_syscall (which does the return of an integer, see there) # - emit_syscall (which does the return of an integer, see there)
def putstring( context) def putstring( context)
compiler = compiler_for(:Word , :putstring ,{}) compiler = compiler_for(:Word , :putstring ,{})
builder = compiler.compiler_builder(compiler.source) builder = compiler.builder(compiler.source)
builder.build do builder.build do
word! << message[:receiver] word! << message[:receiver]
integer! << word[Parfait::Word.get_length_index] integer! << word[Parfait::Word.get_length_index]
@ -26,7 +26,7 @@ module Risc
# return a word sized new int, in return_value # return a word sized new int, in return_value
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.builder(compiler.source).build do
object! << message[:receiver] object! << message[:receiver]
integer! << message[:arguments] integer! << message[:arguments]
integer << integer[1] integer << integer[1]
@ -44,7 +44,7 @@ module Risc
# return value # return value
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.builder(compiler.source).build do
word! << message[:receiver] word! << message[:receiver]
integer! << message[:arguments] integer! << message[:arguments]
integer << integer[1] integer << integer[1]

View File

@ -13,20 +13,16 @@ module Risc
def initialize( callable ) def initialize( callable )
@callable = callable @callable = callable
@regs = [] @regs = []
init_instructions
@current = @risc_instructions
@constants = [] @constants = []
@block_compilers = [] @block_compilers = []
end
attr_reader :risc_instructions , :constants , :block_compilers , :callable
def init_instructions
@risc_instructions = Risc.label(source_name, source_name) @risc_instructions = Risc.label(source_name, source_name)
@risc_instructions.append Risc.label( source_name, "return_label") @current = @risc_instructions
@risc_instructions.append Mom::ReturnSequence.new.to_risc(self) add_code Risc.label( source_name, "return_label")
@risc_instructions.append Risc.label( source_name, "unreachable") Mom::ReturnSequence.new.to_risc(self)
add_code Risc.label( source_name, "unreachable")
reset_regs reset_regs
end end
attr_reader :risc_instructions , :constants , :block_compilers , :callable , :current
def return_label def return_label
@risc_instructions.each do |ins| @risc_instructions.each do |ins|
@ -42,8 +38,7 @@ module Risc
while( instruction ) while( instruction )
raise "whats this a #{instruction}" unless instruction.is_a?(Mom::Instruction) raise "whats this a #{instruction}" unless instruction.is_a?(Mom::Instruction)
#puts "adding mom #{instruction.to_s}:#{instruction.next.to_s}" #puts "adding mom #{instruction.to_s}:#{instruction.next.to_s}"
risc = instruction.to_risc( self ) instruction.to_risc( self )
add_code(risc)
reset_regs reset_regs
#puts "adding risc #{risc.to_s}:#{risc.next.to_s}" #puts "adding risc #{risc.to_s}:#{risc.next.to_s}"
instruction = instruction.next instruction = instruction.next
@ -135,19 +130,12 @@ module Risc
# Build with builder (see there), adding the created instructions # Build with builder (see there), adding the created instructions
def build(source , &block) def build(source , &block)
code_builder(source).build(&block) builder(source).build(&block)
end end
# return a new code builder that uses this compiler # return a Builder, that adds the generated code to this compiler
# CodeBuilder returns code after building def builder( source)
def code_builder( source) Builder.new(self , source)
CodeBuilder.new(self , source)
end
# return a CompilerBuilder
# CompilerBuilder adds the generated code to the compiler
def compiler_builder( source)
CompilerBuilder.new(self , source)
end end
end end
end end

View File

@ -45,10 +45,10 @@ module Risc
# using the registers type, resolve the slot to an index # using the registers type, resolve the slot to an index
# Using the index and the register, add a SlotToReg to the instruction # Using the index and the register, add a SlotToReg to the instruction
def resolve_and_add(slot , instruction , compiler) def resolve_and_add(slot , compiler)
index = resolve_index( slot ) index = resolve_index( slot )
new_left = get_new_left( slot , compiler ) new_left = get_new_left( slot , compiler )
instruction << Risc::SlotToReg.new( "SlotLoad #{type}[#{slot}]" , self ,index, new_left) compiler.add_code Risc::SlotToReg.new( "SlotLoad #{type}[#{slot}]" , self ,index, new_left)
new_left new_left
end end

View File

@ -38,7 +38,7 @@ module Vool
runtime_method = Mom::SlotDefinition.new( :message , [ :method] ) runtime_method = Mom::SlotDefinition.new( :message , [ :method] )
check = Mom::NotSameCheck.new(compile_method , runtime_method, ok_label) check = Mom::NotSameCheck.new(compile_method , runtime_method, ok_label)
# TODO? Maybe create mom instructions for this # TODO? Maybe create mom instructions for this
#builder = compiler.code_builder("yield") #builder = compiler.builder("yield")
#Risc::Builtin::Object.exit_sequence(builder) #Risc::Builtin::Object.exit_sequence(builder)
#check << builder.built #check << builder.built
check << ok_label check << ok_label

View File

@ -7,8 +7,12 @@ module Risc
Parfait.boot! Parfait.boot!
Risc.boot! Risc.boot!
init = Parfait.object_space.get_init init = Parfait.object_space.get_init
@builder = Risc::MethodCompiler.new( init ).code_builder(init) @builder = Risc::MethodCompiler.new( init ).builder(init)
@label = Risc.label("source","name") @label = Risc.label("source","name")
@start = @builder.compiler.current
end
def built
@start.next
end end
def test_has_build def test_has_build
assert @builder.respond_to?(:build) assert @builder.respond_to?(:build)
@ -36,34 +40,34 @@ 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 } @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} @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).set_builder( @builder ) r2 = RegisterValue.new(:r2 , :Message).set_builder( @builder )
built = @builder.build{ r2 << space![:next_message] } @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).set_builder( @builder ) r2 = RegisterValue.new(:r2 , :Message).set_builder( @builder )
built = @builder.build{ r2 << space![:next_message] } @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} @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
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ message[:receiver] << r1} @builder.build{ message[:receiver] << r1}
assert_equal RegToSlot , built.class assert_equal RegToSlot , built.class
assert_equal :r0 , built.array.symbol assert_equal :r0 , built.array.symbol
end end

View File

@ -8,7 +8,7 @@ module Risc
Risc.boot! Risc.boot!
@init = Parfait.object_space.get_init @init = Parfait.object_space.get_init
@compiler = Risc::MethodCompiler.new( @init ) @compiler = Risc::MethodCompiler.new( @init )
@builder = @compiler.compiler_builder(@init) @builder = @compiler.builder(@init)
end end
def test_inserts_built def test_inserts_built
r1 = RegisterValue.new(:r1 , :Space) r1 = RegisterValue.new(:r1 , :Space)

View File

@ -8,7 +8,7 @@ module Risc
Risc.boot! Risc.boot!
@init = Parfait.object_space.get_init @init = Parfait.object_space.get_init
@compiler = Risc::MethodCompiler.new( @init ) @compiler = Risc::MethodCompiler.new( @init )
@builder = @compiler.compiler_builder(@init) @builder = @compiler.builder(@init)
end end
def test_list def test_list
assert_equal :List , @builder.infer_type(:list).class_name assert_equal :List , @builder.infer_type(:list).class_name