diff --git a/lib/risc/builtin.rb b/lib/risc/builtin.rb index feb2fd77..85508fef 100644 --- a/lib/risc/builtin.rb +++ b/lib/risc/builtin.rb @@ -12,33 +12,46 @@ module Risc # This should return the implementation of the method (ie a method object), # not actually try to implement it(as that's impossible in ruby) # - def self.boot_functions( ) + def self.boot_functions + compilers = [] space = Parfait.object_space - # very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we - # have to define some dummies, just for the others to compile - # TODO go through the virtual parfait layer and adjust function names to what they really are - space_class = space.get_class - space_class.instance_type.add_method Builtin::Space.send(:main, nil) + # very fiddly chicken 'n egg problem. Functions need to be in the right order, + # and in fact we have to define some dummies, just for the others to compile + # TODO go through the virtual parfait layer and adjust function names + # to what they really are + space_type = space.get_class.instance_type + compilers << compiler_for( space_type , Space , :main) - obj = space.get_class_by_name(:Object) + obj_type = space.get_class_by_name(:Object).instance_type [ :get_internal_word , :set_internal_word , :_method_missing, :exit , :__init__].each do |f| - obj.instance_type.add_method Builtin::Object.send(f , nil) + compilers << compiler_for( obj_type , Object , f) end - obj = space.get_class_by_name(:Word) + word_type = space.get_class_by_name(:Word).instance_type [:putstring , :get_internal_byte , :set_internal_byte ].each do |f| - obj.instance_type.add_method Builtin::Word.send(f , nil) + compilers << compiler_for( word_type , Word , f) end - obj = space.get_class_by_name(:Integer) + int_type = space.get_class_by_name(:Integer).instance_type Risc.operators.each do |op| - obj.instance_type.add_method Builtin::Integer.operator_method(op) + compilers << operator_compiler( int_type , op) end [:putint, :div4, :div10 , :<,:<= , :>=, :>].each do |f| #div4 is just a forward declaration - obj.instance_type.add_method Builtin::Integer.send(f , nil) + compilers << compiler_for( int_type , Integer , f) end + compilers end + def self.compiler_for( type , mod , name) + compiler = mod.send(name , nil) + type.add_method( compiler.method ) + compiler + end + def self.operator_compiler(int_type , op) + compiler = Integer.operator_method(op) + int_type.add_method(compiler.method) + compiler + end end end diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb index 8a0c9936..2eae1785 100644 --- a/lib/risc/builtin/integer.rb +++ b/lib/risc/builtin/integer.rb @@ -17,7 +17,7 @@ module Risc builder.add_new_int(source,me , two) builder.add_reg_to_slot( source , two , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end def >( context ) comparison( :> ) @@ -54,12 +54,12 @@ module Risc builder.add_code merge_label builder.add_reg_to_slot( "#{operator} save ret" , other , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end def putint(context) compiler = compiler_for(:Integer,:putint ,{}) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end def operator_method( op_sym ) compiler = compiler_for(:Integer, op_sym ,{other: :Integer}) @@ -71,7 +71,7 @@ module Risc builder.add_new_int(op_sym.to_s + " new int", me , other) builder.add_reg_to_slot( op_sym.to_s + "save ret" , other , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end def div10( context ) s = "div_10 " @@ -134,7 +134,7 @@ module Risc builder.add_reg_to_slot( s , tmp , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end end extend ClassMethods diff --git a/lib/risc/builtin/object.rb b/lib/risc/builtin/object.rb index e1cdf121..4b90dec8 100644 --- a/lib/risc/builtin/object.rb +++ b/lib/risc/builtin/object.rb @@ -17,7 +17,7 @@ module Risc # and put it back into the return value builder.add_reg_to_slot( source , me , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end # self[index] = val basically. Index is the first arg , value the second @@ -31,7 +31,7 @@ module Risc # do the set builder.add_reg_to_slot( source , value , me , index) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end # every object needs a method missing. @@ -39,7 +39,7 @@ module Risc def _method_missing( context ) compiler = compiler_for(:Object,:method_missing ,{}) emit_syscall( compiler.compiler_builder(compiler.method) , :exit ) - return compiler.method + return compiler end # this is the really really first place the machine starts (apart from the jump here) @@ -73,7 +73,7 @@ module Risc end compiler.reset_regs exit_sequence(builder) - return compiler.method + return compiler end # a sort of inline version of exit method. @@ -89,7 +89,7 @@ module Risc compiler = compiler_for(:Object,:exit ,{}) builder = compiler.compiler_builder(compiler.method) exit_sequence(builder) - return compiler.method + return compiler end def emit_syscall( builder , name ) diff --git a/lib/risc/builtin/space.rb b/lib/risc/builtin/space.rb index 3a236fb3..0d7fa7fb 100644 --- a/lib/risc/builtin/space.rb +++ b/lib/risc/builtin/space.rb @@ -10,7 +10,7 @@ module Risc def main(context) compiler = compiler_for(:Space , :main ,{args: :Integer}) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end end diff --git a/lib/risc/builtin/word.rb b/lib/risc/builtin/word.rb index 51e14101..3cdbaa08 100644 --- a/lib/risc/builtin/word.rb +++ b/lib/risc/builtin/word.rb @@ -13,7 +13,7 @@ module Risc builder.add_slot_to_reg( "putstring" , :new_message , index , reg ) Risc::Builtin::Object.emit_syscall( builder , :putstring ) compiler.add_mom( Mom::ReturnSequence.new) - compiler.method + compiler end # self[index] basically. Index is the first arg > 0 @@ -30,7 +30,7 @@ module Risc # and put it back into the return value builder.add_reg_to_slot( source , index , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end # self[index] = val basically. Index is the first arg ( >0), @@ -48,7 +48,7 @@ module Risc value = builder.load_int_arg_at(source , 1 ) builder.add_reg_to_slot( source , value , :message , :return_value) compiler.add_mom( Mom::ReturnSequence.new) - return compiler.method + return compiler end end diff --git a/test/risc/test_builtin.rb b/test/risc/test_builtin.rb new file mode 100644 index 00000000..1f3b1ad4 --- /dev/null +++ b/test/risc/test_builtin.rb @@ -0,0 +1,22 @@ +require_relative "helper" + +module Risc + class TestBuiltinFunction < MiniTest::Test + + def setup + Parfait.boot! + end + def test_has_boot_function + assert Builtin.boot_functions + end + def test_boot_function_type + assert_equal Array, Builtin.boot_functions.class + end + def test_boot_function_length + assert_equal 23, Builtin.boot_functions.length + end + def test_boot_function_first + assert_equal RiscCompiler, Builtin.boot_functions.first.class + end + end +end