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
#
# There are two subclasses of Builder, depending of what one wants to do with the
# 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
# The code is added to the method_compiler.
#
class Builder
@ -19,6 +12,7 @@ module Risc
# second arg determines weather instructions are added (default true)
# call build with a block to build
def initialize(compiler, for_source)
raise "no compiler" unless compiler
@compiler = compiler
@source = for_source
@source_used = false
@ -119,16 +113,16 @@ module Risc
# 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, if the
# builder is created with default args
# build result is added to compiler directly
#
def build(&block)
instance_eval(&block)
@built
end
# add code straight to the compiler
def add_code(ins)
raise "Must be implemented in subclass #{self}"
@compiler.add_code(ins)
return ins
end
# move a machine int from register "from" to a Parfait::Integer in register "to"
@ -146,39 +140,4 @@ module Risc
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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,10 +45,10 @@ module Risc
# using the registers type, resolve the slot to an index
# 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 )
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
end

View File

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

View File

@ -7,8 +7,12 @@ module Risc
Parfait.boot!
Risc.boot!
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")
@start = @builder.compiler.current
end
def built
@start.next
end
def test_has_build
assert @builder.respond_to?(:build)
@ -36,34 +40,34 @@ module Risc
end
def test_returns_built
r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ space! << r1 }
@builder.build{ space! << r1 }
assert_equal Transfer , built.class
end
def test_returns_two
r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ space! << r1 ; space << r1}
@builder.build{ space! << r1 ; space << r1}
assert_equal Transfer , built.next.class
end
def test_returns_slot
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 :r1 , built.array.symbol
end
def test_returns_slot_reverse
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 :r1 , built.array.symbol
end
def test_reuses_names
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
end
def test_uses_message_as_message
r1 = RegisterValue.new(:r1 , :Space)
built = @builder.build{ message[:receiver] << r1}
@builder.build{ message[:receiver] << r1}
assert_equal RegToSlot , built.class
assert_equal :r0 , built.array.symbol
end

View File

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

View File

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