This commit is contained in:
Torsten Ruger 2014-05-03 18:51:47 +03:00
parent 845a8cab8b
commit 04e4dc872e
7 changed files with 39 additions and 34 deletions

View File

@ -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

View File

@ -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

View File

@ -46,7 +46,5 @@ module Vm
# TODO check
@args << value
end
end
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ??