diff --git a/lib/arm/arm_platform.rb b/lib/arm/arm_platform.rb index 5f3fef0b..7376a238 100644 --- a/lib/arm/arm_platform.rb +++ b/lib/arm/arm_platform.rb @@ -10,5 +10,8 @@ module Arm def padding 0x11000 - loaded_at end + def num_registers + 16 + end end end diff --git a/lib/risc/block_compiler.rb b/lib/risc/block_compiler.rb index 9d733690..2f76476f 100644 --- a/lib/risc/block_compiler.rb +++ b/lib/risc/block_compiler.rb @@ -1,7 +1,8 @@ module Risc # A BlockCompiler is much like a MethodCompiler, exept for it's for blocks - # This only changes scoping for variables, lsee slot_type + # This only changes scoping for variables, see slot_type + # (dynamic resolve, as needed when the block is passed, is not implemented) # class BlockCompiler < CallableCompiler diff --git a/lib/risc/callable_compiler.rb b/lib/risc/callable_compiler.rb index bec24927..1cf23485 100644 --- a/lib/risc/callable_compiler.rb +++ b/lib/risc/callable_compiler.rb @@ -25,6 +25,7 @@ module Risc end attr_reader :risc_instructions , :constants , :callable , :current + # find the return label. Every methd should have exactly one def return_label @risc_instructions.each do |ins| next unless ins.is_a?(Label) @@ -33,6 +34,7 @@ module Risc end # add a constant (which get created during compilation and need to be linked) + # constants must be Parfait instances def add_constant(const) raise "Must be Parfait #{const}" unless const.is_a?(Parfait::Object) @constants << const diff --git a/lib/risc/interpreter.rb b/lib/risc/interpreter.rb index 236c5843..13d97b5f 100644 --- a/lib/risc/interpreter.rb +++ b/lib/risc/interpreter.rb @@ -29,7 +29,7 @@ module Risc @registers = {} @flags = { :zero => false , :plus => false , :minus => false , :overflow => false } - (0...12).each do |reg| + (0...InterpreterPlatform.new.num_registers).each do |reg| set_register "r#{reg}".to_sym , "r#{reg}:unknown" end @linker = linker diff --git a/lib/risc/interpreter_platform.rb b/lib/risc/interpreter_platform.rb index 69bd93af..e5ad4ec0 100644 --- a/lib/risc/interpreter_platform.rb +++ b/lib/risc/interpreter_platform.rb @@ -10,6 +10,9 @@ module Risc def padding 0x100 - loaded_at end + def num_registers + 16 + end end class Instruction def nil_next diff --git a/lib/risc/platform.rb b/lib/risc/platform.rb index f305f2b2..2af1a5b4 100644 --- a/lib/risc/platform.rb +++ b/lib/risc/platform.rb @@ -13,6 +13,11 @@ module Risc # return an integer where the binary is loaded def loaded_at end + + # return the number of registers the platform supports + def num_registers + end + # Factory method to create a Platform object according to the platform # string given. # Currently only "Arm" and "Interpreter" diff --git a/lib/slot_machine/block_compiler.rb b/lib/slot_machine/block_compiler.rb index 3cfba0e0..16c6df47 100644 --- a/lib/slot_machine/block_compiler.rb +++ b/lib/slot_machine/block_compiler.rb @@ -1,6 +1,10 @@ module SlotMachine - # A BlockCompiler is much like a MehtodCompiler, exept for blocks + # A BlockCompiler is much like a MethodCompiler, except for blocks + # Blocks are much like methods (hence the base classes) , just the + # scope for accessing variables is different. (This only applies to static + # blocks, not ones being passed around. That is undone because it needs runtime + # code to resolve variables) # class BlockCompiler < CallableCompiler @@ -16,6 +20,8 @@ module SlotMachine "#{@method.self_type.name}.init" end + # Create the risc equivalent, which is a also a (Risc) BlockCompiler + # sintructions are converted from slot to risc in instructions_to_risc (in base class) def to_risc risc_compiler = Risc::BlockCompiler.new(@callable , @method , slot_instructions) instructions_to_risc(risc_compiler) diff --git a/lib/slot_machine/callable_compiler.rb b/lib/slot_machine/callable_compiler.rb index 13805a4c..f4dd42c7 100644 --- a/lib/slot_machine/callable_compiler.rb +++ b/lib/slot_machine/callable_compiler.rb @@ -6,6 +6,9 @@ module SlotMachine # - slot_instructions: The sequence of slot level instructions that was compiled to # Instructions derive from class Instruction and form a linked list + # Since we have many different compilers, and they are kept in lists, the + # Util CompilerList encapsulates the list behaviour + # class CallableCompiler include Util::CompilerList @@ -21,6 +24,8 @@ module SlotMachine end attr_reader :slot_instructions , :constants , :callable , :current + # find the return_label, every method should have exactly one (see constructor) + # used during return sequence code generation def return_label @slot_instructions.each do |ins| next unless ins.is_a?(Label) diff --git a/lib/slot_machine/method_compiler.rb b/lib/slot_machine/method_compiler.rb index 20b9cf98..cb1695a0 100644 --- a/lib/slot_machine/method_compiler.rb +++ b/lib/slot_machine/method_compiler.rb @@ -5,6 +5,30 @@ module SlotMachine class MethodCompiler < CallableCompiler + # helper method for builtin mainly + # the class_name is a symbol, which is resolved to the instance_type of that class + # + # return compiler_for_type with the resolved type + # + def self.compiler_for_class( class_name , method_name , args , frame ) + raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol + clazz = Parfait.object_space.get_class_by_name! class_name + compiler_for_type( clazz.instance_type , method_name , args , frame) + end + + # create a method for the given type ( Parfait type object) + # method_name is a Symbol + # args a hash that will be converted to a type + # the created method is set as the current and the given type too + # return the compiler + def self.compiler_for_type( type , method_name , args , frame) + raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type + raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type) + raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol + method = type.create_method( method_name , args , frame) + self.new(method) + end + def initialize( method ) super(method) end @@ -30,38 +54,13 @@ module SlotMachine risc_compiler end - # helper method for builtin mainly - # the class_name is a symbol, which is resolved to the instance_type of that class - # - # return compiler_for_type with the resolved type - # - def self.compiler_for_class( class_name , method_name , args , frame ) - raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol - clazz = Parfait.object_space.get_class_by_name! class_name - compiler_for_type( clazz.instance_type , method_name , args , frame) - end - - def add_method_to( target ) - target.add_method( @callable ) - end - + # create a block in the scope of the method. + # Blocks are like other constants, exept with code. + # They need to be compiled, so a list of them is kept def create_block(arg_type , frame_type) @callable.create_block(arg_type ,frame_type) end - # create a method for the given type ( Parfait type object) - # method_name is a Symbol - # args a hash that will be converted to a type - # the created method is set as the current and the given type too - # return the compiler - def self.compiler_for_type( type , method_name , args , frame) - raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type - raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type) - raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol - method = type.create_method( method_name , args , frame) - self.new(method) - end - # determine how given name need to be accsessed. # For methods the options are args or frame def slot_type_for(name) diff --git a/test/arm/test_arm_platform.rb b/test/arm/test_arm_platform.rb index 9e141545..fbd7cbb8 100644 --- a/test/arm/test_arm_platform.rb +++ b/test/arm/test_arm_platform.rb @@ -14,5 +14,8 @@ module Arm def test_platform_loaded_class assert_equal ::Integer , @arm.loaded_at.class end + def test_registers + assert_equal 16 , @arm.num_registers + end end end diff --git a/test/risc/test_interpreter.rb b/test/risc/test_interpreter.rb index 7d133fd3..93cfe412 100644 --- a/test/risc/test_interpreter.rb +++ b/test/risc/test_interpreter.rb @@ -20,7 +20,7 @@ module Risc assert_equal :stopped , Interpreter.new(@linker).state end def test_has_regs - assert_equal 12 , Interpreter.new(@linker).registers.length + assert_equal 16 , Interpreter.new(@linker).registers.length end def test_has_r0 assert_equal :r0 , Interpreter.new(@linker).registers.keys.first diff --git a/test/risc/test_interpreter_platform.rb b/test/risc/test_interpreter_platform.rb index ba4e2774..2a6f040e 100644 --- a/test/risc/test_interpreter_platform.rb +++ b/test/risc/test_interpreter_platform.rb @@ -17,6 +17,9 @@ module Risc def test_translator assert IdentityTranslator.new end + def test_registers + assert_equal 16 , @inter.num_registers + end end class TestIdentityTranslator < MiniTest::Test diff --git a/test/sol/send/test_not_found.rb b/test/sol/send/test_not_found.rb index ffab9cfe..c9e68a5e 100644 --- a/test/sol/send/test_not_found.rb +++ b/test/sol/send/test_not_found.rb @@ -1,7 +1,7 @@ require_relative "../helper" module Sol - class TestSendCachedSimpleSlotMachine < MiniTest::Test + class TestNotFoundSlotMachine < MiniTest::Test include SolCompile def setup