From f08d9659fc2e3faa4af68e2ead1aaa5304edcc74 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Mon, 1 Jun 2015 08:33:23 +0300 Subject: [PATCH] getting the symbols to work --- lib/register/assembler.rb | 20 +++++++-------- lib/register/passes/set_implementation.rb | 2 +- lib/virtual/machine.rb | 27 +++----------------- lib/virtual/parfait_adapter.rb | 29 ++++++++++++++++++++++ lib/virtual/passes/collector.rb | 5 +++- lib/virtual/passes/frame_implementation.rb | 4 +-- lib/virtual/passes/minimizer.rb | 4 +-- test/fragments/helper.rb | 2 +- test/virtual/virtual_helper.rb | 2 +- 9 files changed, 53 insertions(+), 42 deletions(-) diff --git a/lib/register/assembler.rb b/lib/register/assembler.rb index c2c213d7..1f056e7a 100644 --- a/lib/register/assembler.rb +++ b/lib/register/assembler.rb @@ -45,16 +45,15 @@ module Register objekt.set_position at at += objekt.mem_length end - @machine.objects.each do |objekt| - objekt.position - end - end def assemble # must be same order as link begin link + @machine.objects.each do |objekt| + objekt.position + end # first we need to create the binary code for the methods @machine.objects.each do |objekt| next unless objekt.is_a? Parfait::Method @@ -88,16 +87,17 @@ module Register # and then plonk that binary data into the method.code array def assemble_binary_method method stream = StringIO.new - begin method.info.blocks.each do |block| block.codes.each do |code| + begin code.assemble( stream ) + rescue => e + puts "Method error #{method.name}\n#{Sof::Writer.write(method.info.blocks).to_s[0...2000]}" + puts Sof::Writer.write(code) + raise e + end end end - rescue => e - puts "Method error #{method.name}\n#{Sof::Writer.write(method.info.blocks).to_s[0...2000]}" - raise e - end method.code.fill_with 0 index = 1 stream.each_byte do |b| @@ -204,7 +204,7 @@ module Register def assemble_String( string ) str = string.to_s if string.is_a? Parfait::Word - str = string.to_s if str.is_a? Symbol + str = string.to_s if string.is_a? Symbol word = (str.length + 7) / 32 # all object are multiple of 8 words (7 for header) raise "String too long (implement split string!) #{word}" if word > 15 # first line is integers, convention is that following lines are the same diff --git a/lib/register/passes/set_implementation.rb b/lib/register/passes/set_implementation.rb index 3761e509..d8118d3e 100644 --- a/lib/register/passes/set_implementation.rb +++ b/lib/register/passes/set_implementation.rb @@ -32,7 +32,7 @@ module Register # need a temporay place because of indexed load/store tmp = RegisterReference.tmp_reg # for constants we have to "move" the constants value - if( code.from.is_a? Parfait::Value) + if( code.from.is_a?(Parfait::Value) or code.from.is_a?(Symbol)) move1 = LoadConstant.new( tmp , code.from ) else # while otherwise we "load" move1 = GetSlot.new( tmp , code.from.reg , code.from.index ) diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index 382f3a58..4b7a61e0 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -64,12 +64,6 @@ module Virtual end end - # double check that all objects dependents are really in the space too (debugging) - def double_check - @objects.each do |o| - check o - end - end # Objects are data and get assembled after functions def add_object o return false if @objects.include?(o) @@ -77,21 +71,6 @@ module Virtual true end - # private - def check object , recurse = true - raise "No good #{object.class}" unless @objects.include? object - puts "#{object.class}" - puts "#{object}" if object.class == Parfait::Word - check object.get_layout - return unless recurse - object.get_layout.each do |name| - check name , false - inst = object.instance_variable_get "@#{name}".to_sym - check inst , false - end - end - - # Passes may be added to by anyone who wants # This is intentionally quite flexible, though one sometimes has to watch the order of them # most ordering is achieved by ordering the requires and using add_pass @@ -112,10 +91,10 @@ module Virtual end def self.boot - instance = self.instance + me = self.instance # boot is a verb here. this is a somewhat tricky process which is in it's own file, boot.rb - instance.boot_parfait! - instance + me.boot_parfait! + me end def self.instance @instance ||= Machine.new diff --git a/lib/virtual/parfait_adapter.rb b/lib/virtual/parfait_adapter.rb index 4fce8479..291cd2be 100644 --- a/lib/virtual/parfait_adapter.rb +++ b/lib/virtual/parfait_adapter.rb @@ -73,6 +73,35 @@ class Symbol def get_layout Virtual::Machine.instance.class_mappings[:Word].object_layout end + def mem_length + to_s.length + end + # not the prettiest addition to the game, but it wasn't me who decided symbols are frozen in 2.x + def cache_positions + unless defined?(@@symbol_positions) + @@symbol_positions = {} + end + @@symbol_positions + end + def position + pos = cache_positions[self] + if pos == nil + str = "position accessed but not set, " + str += "Machine has object=#{Virtual::Machine.instance.objects.include?(self)} " + raise str + " for Symbol:#{self}" + end + pos + end + def set_position pos + # resetting of position used to be error, but since relink and dynamic instruction size it is ok. + # in measures (of 32) + old = cache_positions[self] + if old != nil and ((old - pos).abs > 32) + raise "position set again #{pos}!=#{old} for #{self}" + end + cache_positions[self] = pos + end + end module Parfait diff --git a/lib/virtual/passes/collector.rb b/lib/virtual/passes/collector.rb index 87aeb8f5..1707f319 100644 --- a/lib/virtual/passes/collector.rb +++ b/lib/virtual/passes/collector.rb @@ -14,9 +14,12 @@ module Virtual unless object.has_layout? object.init_layout end + if( object.is_a? Parfait::Method) + object.info.constants.each{|c| keep(c) } + end layout = object.get_layout - #puts "Layout #{layout.get_object_class.name} #{Machine.instance.objects.include?(layout)}" keep layout + #puts "Layout #{layout.get_object_class.name} #{Machine.instance.objects.include?(layout)}" layout.each do |name| inst = object.instance_variable_get "@#{name}".to_sym keep inst diff --git a/lib/virtual/passes/frame_implementation.rb b/lib/virtual/passes/frame_implementation.rb index be189898..eecad898 100644 --- a/lib/virtual/passes/frame_implementation.rb +++ b/lib/virtual/passes/frame_implementation.rb @@ -21,9 +21,9 @@ module Virtual def run block block.codes.dup.each do |code| if code.is_a?(NewFrame) - kind = "next_frame" + kind = :next_frame elsif code.is_a?(NewMessage) - kind = "next_message" + kind = :next_message else next end diff --git a/lib/virtual/passes/minimizer.rb b/lib/virtual/passes/minimizer.rb index 2d131f7c..a1b66f32 100644 --- a/lib/virtual/passes/minimizer.rb +++ b/lib/virtual/passes/minimizer.rb @@ -22,13 +22,13 @@ module Virtual puts "function was already removed #{ function.name}" return end + #puts "stayer #{function.name}" @gonners.delete function function.info.blocks.each do |block| block.codes.each do |code| if code.is_a? Virtual::MessageSend - str_name = code.name.to_s @gonners.each do |stay| - remove stay if(stay.name == str_name) + remove stay if(stay.name == code.name) end end remove code.method if code.is_a? Virtual::MethodCall diff --git a/test/fragments/helper.rb b/test/fragments/helper.rb index fe4ffd17..8f8467df 100644 --- a/test/fragments/helper.rb +++ b/test/fragments/helper.rb @@ -13,7 +13,7 @@ require 'parslet/convenience' module Fragments # need a code generator, for arm def setup - @object_machine = Virtual::Machine.new "Arm" + @object_machine = Virtual::Machin.new "Arm" end def parse diff --git a/test/virtual/virtual_helper.rb b/test/virtual/virtual_helper.rb index 1ec58ec6..ad7cfaec 100644 --- a/test/virtual/virtual_helper.rb +++ b/test/virtual/virtual_helper.rb @@ -9,7 +9,7 @@ module VirtualHelper end def check - machine = Virtual::Machine.reboot + machine = Virtual::Machine.boot expressions = machine.compile_main @string_input if( expressions.first.is_a? Parfait::Method ) # stops the whole objectspace beeing tested