diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index 2cbeb054..18f6548f 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -9,5 +9,12 @@ module Arm def function_call call_value "call" end + + def main_entry + e = Vm::Block.new("main_entry") + end + def main_exit + e = Vm::Block.new("main_exit") + end end end \ No newline at end of file diff --git a/lib/vm/block.rb b/lib/vm/block.rb index d0bc541f..c321e6f2 100644 --- a/lib/vm/block.rb +++ b/lib/vm/block.rb @@ -21,21 +21,24 @@ module Vm def initialize(name) super() @name = name.to_sym + @next = nil + @previous = nil + @codes = [] end - attr_reader :name + attr_reader :name , :previous , :next def verify - raise "Empty #{self.inspect}" if @values.empty? - end - private - - # possibly misguided ?? - def add_arg value - # TODO check - @args << value end + # set the next executed block after self. + # why is this useful? if it's unconditional, why not merge them: + # So the second block can be used as a jump target. You standard loop needs a block to setup + # and at least one to do the calculation + def next block + block.previous = self + self.next = block + end end end \ No newline at end of file diff --git a/lib/vm/function.rb b/lib/vm/function.rb index 06001ad1..51c98b14 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -46,7 +46,5 @@ module Vm # TODO check @args << value end - end - end \ No newline at end of file diff --git a/lib/vm/kernel.rb b/lib/vm/kernel.rb index 0afe1f5c..47faeb47 100644 --- a/lib/vm/kernel.rb +++ b/lib/vm/kernel.rb @@ -2,12 +2,15 @@ module Vm module Kernel def self.start #TODO extract args into array of strings + Machine.instance.main_entry end def self.exit # Machine.exit swi 0 + Machine.instance.main_exit end - def self.puts - "me" + def self.puts string + # should unwrap from string to char* + Machine.instance.puts end end end \ No newline at end of file diff --git a/lib/vm/program.rb b/lib/vm/program.rb index 84130fc7..6dde3467 100644 --- a/lib/vm/program.rb +++ b/lib/vm/program.rb @@ -15,15 +15,14 @@ module Vm # in terms of variables and their visibility, things are simple. They are either local or global # throwing in a context for unspecified use (well one is to pass the programm/globals around) - class Program < Block - # should init for a machine and pass that on to start/exit / register alloc and the like - def initialize + # Initialize with a string for cpu. Naming conventions are: for Machine XXX there exists a module XXX + # with a XXXMachine in it that derives from Vm::Machine + def initialize machine super("start") - # this aint pretty. but i'll go soon enough - Machine.instance = Arm::ArmMachine.new + Machine.instance = eval("#{machine}::#{machine}Machine").new @context = Context.new(self) @functions = [] @@ -60,8 +59,6 @@ module Vm end def verify - main = @functions.find{|f| f.name == "main"} - raise "No main in Program" unless main @functions.each do |funct| funct.verify end diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 1e04ead1..9e311662 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -25,6 +25,11 @@ module Vm raise "abstract method called #{self.inspect}" end + # since we convert ast to values in conversion, value itself is responsible for compiling itself + # Compile must return a value, usually used in the next level up + def compile(context) + raise "abstract method called #{self.inspect}" + end end class Word < Value @@ -36,19 +41,13 @@ module Vm class Unsigned < Word def plus unsigned - unless unsigned.is_a? Unsigned - unsigned = Conversion.new( unsigned , Unsigned ) - end - UnsignedAdd.new( self , unsigned ) + Machine.instance.unsigned_plus self , unsigned end end class Signed < Word def plus signed - unless signed.is_a? Signed - signed = Conversion.new( signed , Signed ) - end - SignedAdd.new( self , signed ) + Machine.instance.signed_plus self , signed end end diff --git a/test/test_runner.rb b/test/test_runner.rb index 85cbbabb..8cb56d77 100644 --- a/test/test_runner.rb +++ b/test/test_runner.rb @@ -20,12 +20,10 @@ class TestRunner < MiniTest::Test string = File.read(file) syntax = Parser::Composed.new.parse(string) tree = Parser::Transform.new.apply(syntax) - #transform - # write - #link - # execute - # check result ? - program = Vm::Program.new + + puts tree.to_yaml + + program = Vm::Program.new "Arm" expression = tree.to_value compiled = expression.compile( program.context ) # do some stuff with mains and what not ??