diff --git a/lib/interpreter/interpreter.rb b/lib/interpreter/interpreter.rb index 11950f42..b476fe42 100644 --- a/lib/interpreter/interpreter.rb +++ b/lib/interpreter/interpreter.rb @@ -10,8 +10,6 @@ module Interpreter attr_reader :clock # current instruction or pc # an (arm style) link register. store the return address to return to attr_reader :link - # current executing block. since this is not a hardware simulator this is luxury - attr_reader :block attr_reader :registers # the registers, 16 (a hash, sym -> contents) attr_reader :stdout # collect the output attr_reader :state # running etc @@ -27,13 +25,12 @@ module Interpreter (0...12).each do |r| set_register "r#{r}".to_sym , "r#{r}:unknown" end - @block = nil end - def start bl + def start instruction @clock = 0 set_state(:running) - set_block bl + set_instruction instruction end def set_state state @@ -43,20 +40,6 @@ module Interpreter trigger(:state_changed , old , state ) end - def set_block bl - return if @block == bl - raise "Error, nil block" unless bl - old = @block - if bl.codes.empty? - next_b = @block.method.source.blocks.index(bl) + 1 - bl = @block.method.source.blocks[next_b] - end - raise "Block #{bl.codes.empty?}" if bl.codes.empty? #just fixed, leave for next time - @block = bl - trigger(:block_changed , old , bl) - set_instruction bl.codes.first - end - def set_instruction i return if @instruction == i old = @instruction @@ -88,7 +71,6 @@ module Interpreter def tick return unless @instruction @clock += 1 - #puts @instruction name = @instruction.class.name.split("::").last fetch = send "execute_#{name}" return unless fetch @@ -96,12 +78,7 @@ module Interpreter end def fetch_next_intruction - if(@instruction != @block.codes.last) - set_instruction @block.codes[ @block.codes.index(@instruction) + 1] - else - next_b = @block.method.source.blocks.index(@block) + 1 - set_block @block.method.source.blocks[next_b] - end + set_instruction @instruction.next end def object_for reg @@ -110,10 +87,14 @@ module Interpreter object.nil? ? id : object end + # Label is a noop. + def execute_Label + true + end # Instruction interpretation starts here def execute_Branch - target = @instruction.block - set_block target + label = @instruction.label + set_instruction label false end @@ -161,10 +142,9 @@ module Interpreter end def execute_FunctionCall - @link = [@block , @instruction] + @link = @instruction #puts "Call link #{@link}" - next_block = @instruction.method.source.blocks.first - set_block next_block + set_instruction @instruction.method.source.instructions false end @@ -182,7 +162,7 @@ module Interpreter object = object_for( @instruction.register ) link = object.internal_object_get( @instruction.index ) #puts "FunctionReturn link #{@link}" - @block , @instruction = link + @instruction = link # we jump back to the call instruction. so it is as if the call never happened and we continue true end diff --git a/lib/register/block.rb b/lib/register/block.rb deleted file mode 100644 index 6447aee5..00000000 --- a/lib/register/block.rb +++ /dev/null @@ -1,61 +0,0 @@ -module Register - - # Think flowcharts: blocks are the boxes. The smallest unit of linear code - - # Blocks must end in control instructions (jump/call/return). - # And the only valid argument for a jump is a Block - - # Blocks form a graph, which is managed by the method - - class Block - - def initialize(name , method ) - super() - @method = method - raise "Method is not Method, but #{method.class}" unless method == :__init__ or method.is_a?(Parfait::Method) - @name = name.to_sym - @codes = [] - end - - attr_reader :name , :codes , :method , :position - - def add_code kode - @codes << kode - self - end - - # replace a code with an array of new codes. This is what happens in passes all the time - def replace code , new_codes - index = @codes.index code - raise "Code not found #{code} in #{self}" unless index - @codes.delete_at(index) - if( new_codes.is_a? Array) - new_codes.reverse.each {|c| @codes.insert(index , c)} - else - @codes.insert(index , new_codes) - end - end - - # position is what another block uses to jump to. this is determined by the assembler - # the assembler allso assembles and assumes a linear instruction sequence - # Note: this will have to change for plocks and maybe anyway. - def set_position at - @position = at - @codes.each do |code| - begin - code.set_position( at) - rescue => e - puts "BLOCK #{self.to_s[0..5000]}" - raise e - end - raise code.inspect unless code.byte_length - at += code.byte_length - end - end - - def byte_length - @codes.inject(0){|count , instruction| count += instruction.byte_length } - end - - end -end diff --git a/lib/register/builtin/kernel.rb b/lib/register/builtin/kernel.rb index 7219cfbf..30454c8b 100644 --- a/lib/register/builtin/kernel.rb +++ b/lib/register/builtin/kernel.rb @@ -9,8 +9,10 @@ module Register function = MethodSource.create_method(:Kernel,:Integer,:__init__ , []) function.source.set_return_type :Integer # no method enter or return (automatically added), remove - function.source.blocks.first.codes.pop # no Method enter - function.source.blocks.last.codes.pop # no Method return + new_start = Label.new(function , "__init__" ) + function.source.instructions = new_start + function.source.current = new_start + #Set up the Space as self upon init space = Parfait::Space.object_space space_reg = Register.tmp_reg(:Space) diff --git a/lib/register/instruction.rb b/lib/register/instruction.rb index d888827f..46d4857d 100644 --- a/lib/register/instruction.rb +++ b/lib/register/instruction.rb @@ -7,29 +7,54 @@ module Register # but we keep the names for better understanding, r4/5 are temporary/scratch # there is no direct memory access, only through registers # constants can/must be loaded into registers before use + + # Instructions form a graph. + # Linear instructions form a linked list + # Branches fan out, Labels collect + # Labels are the only valid branch targets class Instruction - def initialize source + def initialize source , nekst = nil @source = source + @next = nekst end attr_reader :source - # returns an array of registers (RegisterValues) that this instruction uses. - # ie for r1 = r2 + r3 - # which in assembler is add r1 , r2 , r3 - # it would return [r2,r3] - # for pushes the list may be longer, whereas for a jump empty - def uses - raise "abstract called for #{self.class}" + # set the next instruction (also aliased as <<) + # throw an error if that is set, use insert for that use case + # return the instruction, so chaining works as one wants (not backwards) + def set_next nekst + raise "Next already set #{@next}" if @next + @next = nekst + nekst end - # returns an array of registers (RegisterValues) that this instruction assigns to. - # ie for r1 = r2 + r3 - # which in assembler is add r1 , r2 , r3 - # it would return [r1] - # for most instruction this is one, but comparisons and jumps 0 , and pop's as long as 16 - def assigns - raise "abstract called for #{self.class}" + alias :<< :set_next + + # get the next instruction (without arg given ) + # when given an interger, advance along the line that many time and return. + def next( amount = 1) + (amount == 1) ? @next : @next.next(amount-1) end + # set the give instruction as the next, while moving any existing + # instruction along to the given ones's next. + # ie insert into the linked list that the instructions form + def insert instruction + instruction.set_next @next + @next = instruction + end + + def length labels = [] + ret = 1 + ret += self.next.length( labels ) if self.next + ret + end + + def to_ac labels = [] + ret = [self.class] + ret += self.next.to_ac(labels) if self.next + ret + end + end end @@ -42,5 +67,6 @@ require_relative "instructions/function_call" require_relative "instructions/function_return" require_relative "instructions/save_return" require_relative "instructions/register_transfer" +require_relative "instructions/label" require_relative "instructions/branch" require_relative "instructions/operator_instruction" diff --git a/lib/register/instructions/branch.rb b/lib/register/instructions/branch.rb index d83e5e87..ac11053c 100644 --- a/lib/register/instructions/branch.rb +++ b/lib/register/instructions/branch.rb @@ -6,14 +6,22 @@ module Register def initialize source , to super(source) raise "No block" unless to - @block = to + @label = to end - attr_reader :block + attr_reader :label def to_s - "#{self.class.name}: #{block.name}" + "#{self.class.name}: #{label.name}" end alias :inspect :to_s + + def length labels = [] + super(labels) + self.label.length(labels) + end + + def to_ac labels = [] + super(labels) + self.label.to_ac(labels) + end end class IsZero < Branch diff --git a/lib/register/instructions/label.rb b/lib/register/instructions/label.rb new file mode 100644 index 00000000..e0f62610 --- /dev/null +++ b/lib/register/instructions/label.rb @@ -0,0 +1,34 @@ +module Register + + # A label is a placeholder for it's next Instruction + # It's function is not to turn into code, but to be a valid brnch target + # + # So branches and Labels are pairs, fan out, fan in + # + # + + class Label < Instruction + def initialize source , name , nekst = nil + super(source , nekst) + @name = name + end + attr_reader :name + + def to_s + "Label: #{@name} (#{self.next.class})" + end + + def to_ac labels = [] + return [] if labels.include?(self) + labels << self + self.next.to_ac(labels) + end + + def length labels = [] + return 0 if labels.include?(self) + labels << self + 1 + self.next.length(labels) + end + + end +end diff --git a/lib/register/machine.rb b/lib/register/machine.rb index aba85cfb..18cdc236 100644 --- a/lib/register/machine.rb +++ b/lib/register/machine.rb @@ -117,9 +117,7 @@ module Register def boot boot_parfait! - @init = Block.new("init", :__init__ ) - branch = Branch.new( "__init__" , self.space.get_init.source.blocks.first ) - @init.add_code branch + @init = Branch.new( "__init__" , self.space.get_init.source.instructions ) @booted = true self end diff --git a/lib/register/method_source.rb b/lib/register/method_source.rb index 63be47ff..c7eeba27 100644 --- a/lib/register/method_source.rb +++ b/lib/register/method_source.rb @@ -1,18 +1,8 @@ -require_relative "block" module Register # the static info of a method (with its compiled code, argument names etc ) is part of the # runtime, ie found in Parfait::Method - # the source we create here is injected into the method and used only at compile-time - - # - # Methods are one step up from to VM::Blocks. Where Blocks can be jumped to, Methods can be called. - - # Methods also have arguments and a return. These are typed by subclass instances of Value - - # They also have local variables. - # Code-wise Methods are made up from a list of Blocks, in a similar way blocks are made up of # Instructions. The function starts with one block, and that has a start and end (return) @@ -55,23 +45,21 @@ module Register end def init method , return_type = nil - # first block we have to create with .new , as new_block assumes a current - enter = Block.new( "enter" , method ) - enter.add_code Register.save_return(self, :message , :return_address) set_return_type( return_type ) - @blocks = [enter] - @current = enter - ret = new_block("return") + @instructions = @current = Label.new(self, "Method_#{method.name}") + add_code enter = Register.save_return(self, :message , :return_address) + add_code Label.new( method, "return") # move the current message to new_message - ret.add_code RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg ) + add_code RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg ) # and restore the message from saved value in new_message - ret.add_code Register.get_slot(self,:new_message , :caller , :message ) + add_code Register.get_slot(self,:new_message , :caller , :message ) #load the return address into pc, affecting return. (other cpus have commands for this, but not arm) - ret.add_code FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) ) + add_code FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) ) + @current = enter @constants = [] end - attr_reader :blocks , :constants , :return_type - attr_accessor :current , :receiver + attr_reader :constants , :return_type + attr_accessor :current , :receiver , :instructions def set_return_type type return if type.nil? @@ -84,85 +72,25 @@ module Register unless instruction.is_a?(Instruction) raise instruction.to_s end - @current.add_code(instruction) #insert after current + @current.insert(instruction) #insert after current + @current = instruction self end - # return a list of registers that are still in use after the given block - # a call_site uses pushes and pops these to make them available for code after a call - # def locals_at l_block - # used =[] - # # call assigns the return register, but as it is in l_block, it is not asked. - # assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ] - # l_block.reachable.each do |b| - # b.uses.each {|u| - # (used << u) unless assigned.include?(u) - # } - # assigned += b.assigns - # end - # used.uniq - # end - - # control structures need to see blocks as a graph, but they are stored as a list with implict - # branches - # So when creating a new block (with new_block), it is only added to the list, but instructions - # still go to the current one - # With this function one can change the current block, to actually code it. - # This juggling is (unfortunately) neccessary, as all compile functions just keep puring their - # code into the method and don't care what other compiles (like if's) do. - - # Example: while, needs 2 extra blocks - # 1 condition code, must be its own blockas we jump back to it - # - the body, can actually be after the condition as we don't need to jump there - # 2 after while block. Condition jumps here - # After block 2, the function is linear again and the calling code does not need to know what - # happened - - # But subsequent statements are still using the original block (self) to add code to - # So the while statement creates the extra blocks, adds them and the code and then "moves" - # the insertion point along - def current block - @current = block + # set the insertion point (where code is added with add_code) + def current ins + @current = ins self end - # create a new linear block after the current insertion block. - # Linear means there is no brach needed from that one to the new one. - # Usually the new one just serves as jump address for a control statement - # In code generation , the new_block is written after this one, ie zero runtime cost - # This does _not_ change the insertion point, that has do be done with insert_at(block) - def new_block new_name - new_b = Block.new( new_name , @blocks.first.method ) - index = @blocks.index( @current ) - @blocks.insert( index + 1 , new_b ) # + one because we want the ne after the insert_at - return new_b - end - - # sugar to create instructions easily. - # any method will be passed on to the RegisterMachine and the result added to the insertion block - # With this trick we can write what looks like assembler, - # Example func.instance_eval - # mov( r1 , r2 ) - # add( r1 , r2 , 4) - # end - # mov and add will be called on Machine and generate Instructions that are then added - # to the current block - # also symbols are supported and wrapped as register usages (for bare metal programming) -# def method_missing(meth, *arguments, &block) -# add_code ::Arm::ArmMachine.send(meth , *arguments) -# end - def byte_length - @blocks.inject(0) { |c , block| c += block.byte_length } + @instructions.byte_length end # position of the function is the position of the entry block, is where we call def set_position at at += 8 #for the 2 header words - @blocks.each do |block| - block.set_position at - at = at + block.byte_length - end + @instructions.set_position at end end diff --git a/lib/soml/compiler/if_statement.rb b/lib/soml/compiler/if_statement.rb index 7c153287..3a08cdf2 100644 --- a/lib/soml/compiler/if_statement.rb +++ b/lib/soml/compiler/if_statement.rb @@ -1,39 +1,35 @@ module Soml Compiler.class_eval do -# if - attr_reader :cond, :if_true, :if_false + # an if evaluates the condition and jumps to the true block if true + # so the else block is automatically after that. + # But then the else needs to jump over the true block unconditionally. def on_if_statement statement branch_type , condition , if_true , if_false = *statement condition = condition.first - # to execute the logic as the if states it, the blocks are the other way around - # so we can the jump over the else if true , - # and the else joins unconditionally after the true_block - merge_block = @method.source.new_block "if_merge" # last one, created first - true_block = @method.source.new_block "if_true" # second, linked in after current, before merge - false_block = @method.source.new_block "if_false" # directly next in order, ie if we don't jump we land here reset_regs - is = process(condition) + process(condition) + branch_class = Object.const_get "Register::Is#{branch_type.capitalize}" + true_block = Register::Label.new(statement, "if_true") add_code branch_class.new( condition , true_block ) - # compile the true block (as we think of it first, even it is second in sequential order) - @method.source.current true_block - - reset_regs - last = process_all(if_true).last - # compile the false block - @method.source.current false_block reset_regs - last = process_all(if_false).last if if_false - add_code Register::Branch.new(statement, merge_block ) + process_all(if_false) if if_false + merge = Register::Label.new(statement , "if_merge") + add_code Register::Branch.new(statement, merge ) + + # compile the true block + add_code true_block + reset_regs + process_all(if_true) #puts "compiled if: end" - @method.source.current merge_block + add_code merge - #TODO should return the union of the true and false types - last + nil # statements don't return anything end end end diff --git a/lib/soml/compiler/while_statement.rb b/lib/soml/compiler/while_statement.rb index 0434b414..0a26b605 100644 --- a/lib/soml/compiler/while_statement.rb +++ b/lib/soml/compiler/while_statement.rb @@ -6,25 +6,25 @@ module Soml branch_type , condition , statements = *statement condition = condition.first - # this is where the while ends and both branches meet - merge = @method.source.new_block("while merge") - # this comes after the current and beofre the merge - start = @method.source.new_block("while_start" ) - @method.source.current start + add_code start = Register::Label.new(statement , "while_start" ) - cond = process(condition) + reset_regs + process(condition) branch_class = Object.const_get "Register::Is#{branch_type.capitalize}" + # this is where the while ends and both branches meet + merge = Register::Label.new(statement , "while_merge") add_code branch_class.new( condition , merge ) - last = process_all(statements).last + reset_regs + process_all(statements) # unconditionally branch to the start add_code Register::Branch.new(statement,start) # continue execution / compiling at the merge block - @method.source.current merge - last + add_code merge + nil # statements don't return anything end end end diff --git a/test/compiler/fragments/test_if.rb b/test/compiler/fragments/test_if.rb index 2b0fef7d..1a4950bf 100644 --- a/test/compiler/fragments/test_if.rb +++ b/test/compiler/fragments/test_if.rb @@ -16,7 +16,7 @@ class Object end end HERE - @length = 22 + @length = 26 check end @@ -31,7 +31,7 @@ class Object end end HERE - @length = 38 + @length = 45 @stdout = "10" check end @@ -53,7 +53,7 @@ class Object end end HERE - @length = 49 + @length = 57 @stdout = "else" check end diff --git a/test/compiler/statements/helper.rb b/test/compiler/statements/helper.rb index 61a766a7..ff4acd41 100644 --- a/test/compiler/statements/helper.rb +++ b/test/compiler/statements/helper.rb @@ -9,16 +9,20 @@ module Statements machine.parse_and_compile @string_input produced = Register.machine.space.get_main.source assert @expect , "No output given" - assert_equal @expect.length , produced.blocks.length , "Block length" - produced.blocks.each_with_index do |b,i| - codes = @expect[i] - assert codes , "No codes for block #{i}" - assert_equal b.codes.length , codes.length , "Code length for block #{i+1}" - b.codes.each_with_index do |c , ii | - assert_equal codes[ii] , c.class , "Block #{i+1} , code #{ii+1}" - end - end - produced.blocks + #assert_equal @expect.length , produced.instructions.length , "instructions length #{produced.instructions.to_ac}" + compare_instructions produced.instructions , @expect + produced.instructions + end + + def compare_instructions instruction , expect + index = 0 + begin + should = expect[index] + assert should , "No instruction at #{index}" + assert_equal instruction.class , should , "Expected at #{index+1}" + index += 1 + instruction = instruction.next + end while( instruction ) end diff --git a/test/compiler/statements/test_assign.rb b/test/compiler/statements/test_assign.rb index c27a2a60..32335f30 100644 --- a/test/compiler/statements/test_assign.rb +++ b/test/compiler/statements/test_assign.rb @@ -16,8 +16,8 @@ int main() end end HERE - @expect = [[SaveReturn,LoadConstant,LoadConstant, - OperatorInstruction,GetSlot,SetSlot],[RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,LoadConstant,OperatorInstruction,GetSlot,SetSlot, + Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -30,7 +30,7 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -42,7 +42,7 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant, GetSlot,SetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant, GetSlot,SetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -54,8 +54,9 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,GetSlot,SetSlot, LoadConstant,SetSlot, - RegisterTransfer,FunctionCall,GetSlot,GetSlot,SetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,GetSlot,SetSlot, LoadConstant,SetSlot, + RegisterTransfer,FunctionCall,GetSlot,GetSlot,SetSlot , + Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -68,10 +69,10 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot,GetSlot] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot,GetSlot , + Label,RegisterTransfer,GetSlot,FunctionReturn] was = check - get = was[0].codes[5] + get = was.next(6) assert_equal GetSlot , get.class assert_equal 3, get.index , "Get to frame index must be offset, not #{get.index}" end @@ -85,9 +86,9 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,SetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,SetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] was = check - set = was[0].codes[2] + set = was.next(3) assert_equal SetSlot , set.class assert_equal 9, set.index , "Set to args index must be offset, not #{set.index}" end @@ -100,9 +101,9 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] was = check - set = was[0].codes[3] + set = was.next(4) assert_equal SetSlot , set.class assert_equal 3, set.index , "Set to frame index must be offset, not #{set.index}" end @@ -117,10 +118,9 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot , Label , RegisterTransfer,GetSlot,FunctionReturn] was = check - get = was[0].codes[1] + get = was.next(2) assert_equal GetSlot , get.class assert_equal 9, get.index , "Get to frame index must be offset, not #{get.index}" end diff --git a/test/compiler/statements/test_call.rb b/test/compiler/statements/test_call.rb index 6a2f8256..6ebeee5e 100644 --- a/test/compiler/statements/test_call.rb +++ b/test/compiler/statements/test_call.rb @@ -17,9 +17,9 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,LoadConstant, - SetSlot,LoadConstant,SetSlot,RegisterTransfer,FunctionCall,GetSlot] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,LoadConstant, + SetSlot,LoadConstant,SetSlot,RegisterTransfer,FunctionCall,GetSlot , + Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -37,9 +37,9 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,LoadConstant, - SetSlot,LoadConstant,SetSlot,RegisterTransfer,FunctionCall,GetSlot] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,LoadConstant, + SetSlot,LoadConstant,SetSlot,RegisterTransfer,FunctionCall,GetSlot , + Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -57,9 +57,9 @@ class Object end end HERE - @expect = [ [SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot, + @expect = [ Label, SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot, GetSlot,GetSlot,SetSlot,LoadConstant,SetSlot,RegisterTransfer,FunctionCall, - GetSlot] ,[RegisterTransfer,GetSlot,FunctionReturn] ] + GetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -77,9 +77,9 @@ class Object end end HERE - @expect = [ [SaveReturn,GetSlot,GetSlot,GetSlot,SetSlot, + @expect = [ Label, SaveReturn,GetSlot,GetSlot,GetSlot,SetSlot, LoadConstant,SetSlot,RegisterTransfer,FunctionCall, - GetSlot] ,[RegisterTransfer,GetSlot,FunctionReturn] ] + GetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -94,11 +94,11 @@ int main() end end HERE - @expect = [ [SaveReturn , GetSlot,GetSlot,SetSlot,LoadConstant,SetSlot,LoadConstant, - SetSlot,RegisterTransfer,FunctionCall,GetSlot], - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [ Label, SaveReturn , GetSlot,GetSlot,SetSlot,LoadConstant,SetSlot,LoadConstant, + SetSlot,RegisterTransfer,FunctionCall,GetSlot, + Label,RegisterTransfer,GetSlot,FunctionReturn] was = check - set = was[0].codes[7] + set = was.next(8) assert_equal SetSlot , set.class assert_equal 9, set.index , "Set to message must be offset, not #{set.index}" end diff --git a/test/compiler/statements/test_if.rb b/test/compiler/statements/test_if.rb index 990d2480..3bc7ca13 100644 --- a/test/compiler/statements/test_if.rb +++ b/test/compiler/statements/test_if.rb @@ -16,10 +16,9 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,LoadConstant, - OperatorInstruction,IsPlus] , - [LoadConstant,Branch] ,[LoadConstant] ,[] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,LoadConstant, OperatorInstruction,IsPlus , + LoadConstant,Branch , Label , LoadConstant , + Label,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -34,10 +33,9 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,LoadConstant, - OperatorInstruction,IsMinus] , - [Branch] ,[LoadConstant] ,[] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,LoadConstant, OperatorInstruction,IsMinus , + Branch ,Label , LoadConstant , + Label,Label , RegisterTransfer,GetSlot,FunctionReturn] check end @@ -52,10 +50,9 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,LoadConstant, - OperatorInstruction,IsZero] , - [Branch] ,[LoadConstant] ,[] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,LoadConstant,OperatorInstruction,IsZero , + Branch , Label , LoadConstant , + Label,Label, RegisterTransfer,GetSlot,FunctionReturn] check end end diff --git a/test/compiler/statements/test_return.rb b/test/compiler/statements/test_return.rb index bebff832..09bd77dc 100644 --- a/test/compiler/statements/test_return.rb +++ b/test/compiler/statements/test_return.rb @@ -13,7 +13,7 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -26,7 +26,7 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,GetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,GetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -39,8 +39,8 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot,GetSlot] , - [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot,GetSlot,GetSlot , + Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -53,7 +53,7 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,GetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,GetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -65,8 +65,8 @@ class Object end end HERE - @expect = [[SaveReturn,GetSlot,GetSlot,SetSlot, LoadConstant, - SetSlot,RegisterTransfer,FunctionCall,GetSlot] , [RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,GetSlot,GetSlot,SetSlot, LoadConstant, + SetSlot,RegisterTransfer,FunctionCall,GetSlot ,Label,RegisterTransfer,GetSlot,FunctionReturn] check end end diff --git a/test/compiler/statements/test_while.rb b/test/compiler/statements/test_while.rb index 17ed89cc..ad56a8e6 100644 --- a/test/compiler/statements/test_while.rb +++ b/test/compiler/statements/test_while.rb @@ -15,8 +15,8 @@ class Object end end HERE - @expect = [[SaveReturn],[LoadConstant,IsPlus,LoadConstant,Branch], - [],[RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,Label,LoadConstant,IsPlus,LoadConstant,Branch, + Label,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -28,12 +28,13 @@ class Object while_plus(n) n = n - 1 end + return n end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot],[GetSlot,GetSlot, IsPlus,GetSlot, - GetSlot,LoadConstant,OperatorInstruction,GetSlot,SetSlot,Branch], - [],[RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot,Label,GetSlot,GetSlot, IsPlus,GetSlot, + GetSlot,LoadConstant,OperatorInstruction,GetSlot,SetSlot,Branch, + Label,GetSlot,GetSlot,Label,RegisterTransfer,GetSlot,FunctionReturn] check end @@ -50,11 +51,11 @@ class Object end end HERE - @expect = [[SaveReturn,LoadConstant,GetSlot,SetSlot], - [GetSlot,GetSlot,LoadConstant,OperatorInstruction,IsPlus,GetSlot, - GetSlot,LoadConstant,OperatorInstruction,GetSlot,SetSlot,GetSlot, - GetSlot,Branch] , - [],[RegisterTransfer,GetSlot,FunctionReturn]] + @expect = [Label, SaveReturn,LoadConstant,GetSlot,SetSlot,Label, + GetSlot,GetSlot,LoadConstant,OperatorInstruction,IsPlus, + GetSlot, GetSlot,LoadConstant,OperatorInstruction, GetSlot, + SetSlot,GetSlot, GetSlot,Branch , Label , + Label , RegisterTransfer,GetSlot,FunctionReturn] check end end diff --git a/test/elf/test_hello.rb b/test/elf/test_hello.rb index d43a1af8..c221c4ed 100644 --- a/test/elf/test_hello.rb +++ b/test/elf/test_hello.rb @@ -16,7 +16,7 @@ class HelloTest < MiniTest::Test writer.save "hello.o" end - def test_string_put + def pest_string_put @string_input = <