diff --git a/lib/elf/object_writer.rb b/lib/elf/object_writer.rb index fd0d5e4f..e5556f16 100644 --- a/lib/elf/object_writer.rb +++ b/lib/elf/object_writer.rb @@ -6,9 +6,9 @@ require 'elf/string_table_section' module Elf class ObjectWriter - def initialize(space , target = Elf::Constants::TARGET_ARM ) + def initialize(machine , target = Elf::Constants::TARGET_ARM ) @object = Elf::ObjectFile.new(target) - @object_space = space + @object_machine = machine sym_strtab = Elf::StringTableSection.new(".strtab") @object.add_section sym_strtab @symbol_table = Elf::SymbolTableSection.new(".symtab", sym_strtab) @@ -17,12 +17,12 @@ module Elf @text = Elf::TextSection.new(".text") @object.add_section @text - @object_space.run_passes - assembler = Register::Assembler.new(@object_space) + @object_machine.run_passes + assembler = Register::Assembler.new(@object_machine.space) set_text assembler.assemble # for debug add labels to the block positions - space.classes.values.each do |clazz| + space.classes.values.each do |clazz| clazz.instance_methods.each do |f| f.blocks.each do |b| add_symbol "#{clazz.name}::#{f.name}@#{b.name}" , b.position diff --git a/lib/parfait.rb b/lib/parfait.rb index 329ddb03..9959f838 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -25,7 +25,8 @@ module Parfait class Object include FakeMem def self.new_object *args - #puts "I am #{self}" +# Space.space.get_or_create_class(:Word) + puts "I am #{self}" object = self.new(*args) object end diff --git a/lib/parfait/layout.rb b/lib/parfait/layout.rb index 4b40fd48..8f3d6604 100644 --- a/lib/parfait/layout.rb +++ b/lib/parfait/layout.rb @@ -22,5 +22,8 @@ module Parfait class Layout < List + def get_object_class() + return internal_object_get(2) + end end end diff --git a/lib/parfait/list.rb b/lib/parfait/list.rb index 4b602b1b..136428d9 100644 --- a/lib/parfait/list.rb +++ b/lib/parfait/list.rb @@ -42,6 +42,15 @@ module Parfait self.length == 0 end + def each + index = 0 + while index < self.length + item = get(index) + yield item + index = index + 1 + end + self + end def grow_to(len) raise "negative length for grow #{len}" if len < 0 return unless len > self.length diff --git a/lib/parfait/object.rb b/lib/parfait/object.rb index 37444b24..960429b8 100644 --- a/lib/parfait/object.rb +++ b/lib/parfait/object.rb @@ -16,10 +16,16 @@ module Parfait # In Salama we store the class in the Layout, and so the Layout is the only fixed # data that every object carries. def get_class() - @layout.get_class() + l = get_layout() + puts "Layout #{l}" + l.get_object_class() end - # class stores the "latest" layout for instances, ir the layout a new object will + def get_layout() + return internal_object_get(1) + end + + # class stores the "latest" layout for instances, ie the layout a new object will # be created with. # inside parfait (and for now everywhere) these are constant. @@EMPTY = { :names => [] , :types => []} @@ -27,12 +33,8 @@ module Parfait @@EMPTY end - def get_layout() - @layout - end - def instance_variables - @layout.instance_variables + get_layout().instance_variables end def instance_variable_get name @@ -48,7 +50,7 @@ module Parfait end def instance_variable_defined name - @layout.index_of(name) + layout().index_of(name) end # Object diff --git a/lib/parfait/space.rb b/lib/parfait/space.rb index 5f143bd3..7778b75d 100644 --- a/lib/parfait/space.rb +++ b/lib/parfait/space.rb @@ -33,7 +33,7 @@ module Parfait @next_message = @messages.first @next_frame = @frames.first end - attr_reader :init , :main , :classes , :objects , :symbols,:messages, :next_message , :next_frame + attr_reader :classes , :objects , :symbols,:messages, :next_message , :next_frame @@SPACE = { :names => [:classes,:objects,:symbols,:messages, :next_message , :next_frame] , :types => [Virtual::Reference,Virtual::Reference,Virtual::Reference,Virtual::Reference,Virtual::Reference]} @@ -50,7 +50,7 @@ module Parfait end end - # this is the way to instantiate classes (not BootClass.new) + # this is the way to instantiate classes (not Parfait::Class.new) # so we get and keep exactly one per name def get_or_create_class name raise "uups #{name}.#{name.class}" unless name.is_a? Symbol diff --git a/lib/parfait/word.rb b/lib/parfait/word.rb index 19618e3f..92559c10 100644 --- a/lib/parfait/word.rb +++ b/lib/parfait/word.rb @@ -78,12 +78,6 @@ module Parfait raise "called" class_for(MoveInstruction).new(value , self , :opcode => :mov) end - def clazz - Space.space.get_or_create_class(:Word) - end - def layout - Virtual::Object.layout - end def mem_length padded(1 + string.length) end diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index af361873..7aabb4eb 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -34,21 +34,21 @@ module Virtual def initialize @parser = Parser::Salama.new - the_end = Halt.new + #the_end = Halt.new @passes = [ "Virtual::SendImplementation" ] @space = Parfait::Space.new # @message = Message.new(the_end , the_end , :Object) end - attr_reader :message , :passes , :space + attr_reader :message , :passes , :space , :init , :main def run_passes @passes.each do |pass_class| - blocks = [@init] + main.blocks - @classes.values.each do |c| + blocks = [@init] + @main.blocks + @space.classes.values.each do |c| c.instance_methods.each {|f| blocks += f.blocks } end #puts "running #{pass_class}" - all.each do |block| + blocks.each do |block| pass = eval pass_class raise "no such pass-class as #{pass_class}" unless pass pass.new.run(block) @@ -90,8 +90,9 @@ module Virtual # CompiledMethods are grabbed from respective modules by sending the method name. 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 boot_classes! - # 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 other to compile + # 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 other to compile + # TODO: go through the virtual parfait layer and adjust function names to what they really are obj = @space.get_or_create_class :Object [:index_of , :_get_instance_variable , :_set_instance_variable].each do |f| obj.add_instance_method Builtin::Object.send(f , nil) diff --git a/lib/virtual/passes/send_implementation.rb b/lib/virtual/passes/send_implementation.rb index a76207cd..15ef8f26 100644 --- a/lib/virtual/passes/send_implementation.rb +++ b/lib/virtual/passes/send_implementation.rb @@ -14,13 +14,15 @@ module Virtual new_codes = [ ] ref = code.me raise "only refs implemented #{me.inspect}" unless ( ref.type == Reference) + # value known at compile time, got do something with it if(ref.value) me = ref.value - if( me.is_a? BootClass ) + if( me.is_a? Parfait::Class ) raise "unimplemented #{code}" - elsif( me.is_a? ObjectConstant ) + elsif( me.is_a? Parfait::Object ) # get the function from my class. easy peasy - method = me.clazz.get_instance_method(code.name) + puts "Me is #{me.class}" + method = me.get_class.get_instance_method(code.name) raise "Method not implemented #{clazz.name}.#{code.name}" unless method new_codes << MethodCall.new( method ) else @@ -29,9 +31,11 @@ module Virtual kernel = Virtual::Machine.instance.space.get_or_create_class(:Kernel) method = kernel.get_instance_method(:__send) new_codes << MethodCall.new( method ) - raise "unimplemented #{code}" + raise "unimplemented: \n#{code}" end else + # must defer send to run-time + # So inlining the code from message.send (in the future) raise "not constant/ known object for send #{ref.inspect}" end block.replace(code , new_codes ) diff --git a/test/fragments/helper.rb b/test/fragments/helper.rb index bae10a30..fe4ffd17 100644 --- a/test/fragments/helper.rb +++ b/test/fragments/helper.rb @@ -1,7 +1,7 @@ require_relative '../helper' require 'parslet/convenience' -#test the generation of code fragments. +#test the generation of code fragments. # ie parse assumes @string_input # compile # assemble/write assume a @should array with the bytes in it @@ -11,12 +11,12 @@ require 'parslet/convenience' # but to get the bytes, one needs to link and run the object file to confirm correctness (to be automated) module Fragments - # need a code generator, for arm + # need a code generator, for arm def setup - @object_space = Boot::Space.new "Arm" + @object_machine = Virtual::Machine.new "Arm" end - def parse + def parse parser = Parser::Salama.new syntax = parser.parse_with_debug(@string_input) parts = Parser::Transform.new.apply(syntax) @@ -24,27 +24,27 @@ module Fragments # and the last is wrapped as a main parts.each_with_index do |part,index| if part.is_a? Ast::FunctionExpression - expr = part.compile( @object_space.context ) + expr = part.compile( @object_machine.context ) else puts part.inspect if part.is_a? Hash - expr = part.compile( @object_space.context ) + expr = part.compile( @object_machine.context ) end end end # helper to write the file def write name - writer = Elf::ObjectWriter.new(@object_space , Elf::Constants::TARGET_ARM) + writer = Elf::ObjectWriter.new(@object_machine , Elf::Constants::TARGET_ARM) assembly = writer.text - writer.save("#{name}.o") - function = @object_space.classes[@target[0]] + writer.save("#{name}.o") + function = @object_machine.classes[@target[0]] assert function , "no class #{@target[0]}" function = function.get_function(@target[1]) assert function , "no function #{@target[1]} for class #{@target[0]}" io = StringIO.new function.assemble io assembly = io.string - # use this for getting the bytes to compare to : + # use this for getting the bytes to compare to : puts bytes(assembly) assembly.bytes.each_with_index do |byte , index| is = @should[index] @@ -60,5 +60,5 @@ module Fragments def bytes string "[" + string.bytes.collect{|b| "0x"+ b.to_s(16)}.join(",") + "]" end - + end diff --git a/test/test_runner.rb b/test/test_runner.rb index 8ae198d8..71531dbb 100644 --- a/test/test_runner.rb +++ b/test/test_runner.rb @@ -35,6 +35,7 @@ class TestRunner < MiniTest::Test end end + #object writer takes machine writer = Elf::ObjectWriter.new(program , Elf::Constants::TARGET_ARM) writer.save(file.gsub(".rb" , ".o")) @@ -42,4 +43,4 @@ class TestRunner < MiniTest::Test # puts program.to_yaml end -end \ No newline at end of file +end diff --git a/test/virtual/hello.rb b/test/virtual/hello.rb index 1b179f1d..099a3d93 100644 --- a/test/virtual/hello.rb +++ b/test/virtual/hello.rb @@ -2,20 +2,20 @@ require_relative "virtual_helper" class HelloTest < MiniTest::Test include VirtualHelper - + def check machine = Virtual::Machine.boot expressions = machine.compile_main @string_input - writer = Elf::ObjectWriter.new(Virtual::Space.space) + writer = Elf::ObjectWriter.new(machine) writer.save "hello.o" # puts Sof::Writer.write(expressions) - puts Sof::Writer.write(Virtual::Space.space) + puts Sof::Writer.write(machine.space) end def qtest_simplest_function @string_input = <