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:
parent
b294208025
commit
57dc6c45bb
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user