fix all tests and a little cleaning

This commit is contained in:
Torsten Ruger 2014-06-14 10:59:25 +03:00
parent 2c26415de7
commit 0dbaebf647
9 changed files with 47 additions and 47 deletions

View File

@ -132,8 +132,8 @@ module Arm
def syscall block , num def syscall block , num
# This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up # This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up
sys = Vm::Integer.new( Vm::RegisterUse.new(:r7) ) sys = Vm::Integer.new( Vm::RegisterReference.new(:r7) )
ret = Vm::Integer.new( Vm::RegisterUse.new(RETURN_REG) ) ret = Vm::Integer.new( Vm::RegisterReference.new(RETURN_REG) )
block.do_add mov( sys , num ) block.do_add mov( sys , num )
block.do_add swi( 0 ) block.do_add swi( 0 )
#todo should write type into r1 according to syscall #todo should write type into r1 according to syscall

View File

@ -6,7 +6,7 @@ module Ast
locals = {} locals = {}
params.each_with_index do |param , index| params.each_with_index do |param , index|
arg = param.name arg = param.name
register = Vm::RegisterUse.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1) register = Vm::RegisterReference.new(Vm::RegisterMachine.instance.receiver_register).next_reg_use(index + 1)
arg_value = Vm::Integer.new(register) arg_value = Vm::Integer.new(register)
locals[arg] = arg_value locals[arg] = arg_value
args << arg_value args << arg_value

View File

@ -40,7 +40,7 @@ module Vm
@args = Array.new(args.length) @args = Array.new(args.length)
args.each_with_index do |arg , i| args.each_with_index do |arg , i|
shouldda = RegisterUse.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1) shouldda = RegisterReference.new(RegisterMachine.instance.receiver_register).next_reg_use(i + 1)
if arg.is_a?(Value) if arg.is_a?(Value)
@args[i] = arg @args[i] = arg
raise "arg #{i} in non std register #{arg.used_register}, expecting #{shouldda}" unless shouldda == arg.used_register raise "arg #{i} in non std register #{arg.used_register}, expecting #{shouldda}" unless shouldda == arg.used_register
@ -88,7 +88,7 @@ module Vm
def locals_at l_block def locals_at l_block
used =[] used =[]
# call assigns the return register, but as it is in l_block, it is not asked. # call assigns the return register, but as it is in l_block, it is not asked.
assigned = [ RegisterUse.new(Vm::RegisterMachine.instance.return_register) ] assigned = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ]
l_block.reachable.each do |b| l_block.reachable.each do |b|
b.uses.each {|u| b.uses.each {|u|
(used << u) unless assigned.include?(u) (used << u) unless assigned.include?(u)

View File

@ -36,7 +36,7 @@ module Vm
atts.delete(:condition_code) if atts[:condition_code] == :al atts.delete(:condition_code) if atts[:condition_code] == :al
atts.empty? ? "" : ", #{atts}" atts.empty? ? "" : ", #{atts}"
end end
# returns an array of registers (RegisterUses) that this instruction uses. # returns an array of registers (RegisterReferences) that this instruction uses.
# ie for r1 = r2 + r3 # ie for r1 = r2 + r3
# which in assembler is add r1 , r2 , r3 # which in assembler is add r1 , r2 , r3
# it would return [r2,r3] # it would return [r2,r3]
@ -44,7 +44,7 @@ module Vm
def uses def uses
raise "abstract called for #{self.class}" raise "abstract called for #{self.class}"
end end
# returns an array of registers (RegisterUses) that this instruction assigns to. # returns an array of registers (RegisterReferences) that this instruction assigns to.
# ie for r1 = r2 + r3 # ie for r1 = r2 + r3
# which in assembler is add r1 , r2 , r3 # which in assembler is add r1 , r2 , r3
# it would return [r1] # it would return [r1]
@ -191,7 +191,7 @@ module Vm
end end
def assigns def assigns
if opcode == :call if opcode == :call
[RegisterUse.new(RegisterMachine.instance.return_register)] [RegisterReference.new(RegisterMachine.instance.return_register)]
else else
[] []
end end

View File

@ -0,0 +1,33 @@
module Vm
# RegisterReference is not the name for a register, "only" for a certain use of it.
# In a way it is like a variable name, a storage location. The location is a register off course,
# but which register can be changed, and _all_ instructions sharing the RegisterReference then use that register
# In other words a simple level of indirection, or change from value to reference sematics.
class RegisterReference
attr_accessor :symbol
def initialize r
if( r.is_a? Fixnum)
r = "r#{r}".to_sym
end
raise "wrong type for register init #{r}" unless r.is_a? Symbol
raise "double r #{r}" if r == :rr1
@symbol = r
end
def == other
return false if other.nil?
return false if other.class != RegisterReference
symbol == other.symbol
end
#helper method to calculate with register symbols
def next_reg_use by = 1
int = @symbol[1,3].to_i
sym = "r#{int + by}".to_sym
RegisterReference.new( sym )
end
end
end

View File

@ -1,4 +1,5 @@
require_relative "code" require_relative "code"
require_relative "register_reference"
module Vm module Vm
@ -7,12 +8,7 @@ module Vm
# The oprerations on values is what makes a machine do things. Operations are captured as # The oprerations on values is what makes a machine do things. Operations are captured as
# subclasses of Instruction and saved to Blocks # subclasses of Instruction and saved to Blocks
# Values are immutable! (that's why they are called values)
# Operations on values _always_ produce new values (conceptionally)
# Values are a way to reason about (create/validate) instructions. # Values are a way to reason about (create/validate) instructions.
# In fact a linked lists of values is created by invoking instructions
# the linked list goes from value to instruction to value, backwards
# Word Values are what fits in a register. Derived classes # Word Values are what fits in a register. Derived classes
# Float, Reference , Integer(s) must fit the same registers # Float, Reference , Integer(s) must fit the same registers
@ -48,35 +44,6 @@ module Vm
end end
end end
# RegisterUSe is _not_ the name for a register, "only" for a certain use of it.
# In a way it is like a variable name, a storage location. The location is a register off course,
# but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register
# In other words a simple level of indirection, or change from value to reference sematics.
class RegisterUse
attr_accessor :symbol
def initialize r
if( r.is_a? Fixnum)
r = "r#{r}".to_sym
end
raise "wrong type for register init #{r}" unless r.is_a? Symbol
raise "double r #{r}" if r == :rr1
@symbol = r
end
def == other
return false if other.nil?
return false if other.class != RegisterUse
symbol == other.symbol
end
#helper method to calculate with register symbols
def next_reg_use by = 1
int = @symbol[1,3].to_i
sym = "r#{int + by}".to_sym
RegisterUse.new( sym )
end
end
# This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base # This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base
# Must be promoted to A Word-Value to to anything makes is_a chaecking easier # Must be promoted to A Word-Value to to anything makes is_a chaecking easier
# remembering that our oo machine is typed, no overloading or stuff # remembering that our oo machine is typed, no overloading or stuff
@ -94,10 +61,10 @@ module Vm
inspect inspect
end end
def initialize reg def initialize reg
if reg.is_a? RegisterUse if reg.is_a? RegisterReference
@used_register = reg @used_register = reg
else else
@used_register = RegisterUse.new(reg) @used_register = RegisterReference.new(reg)
end end
end end
def length def length

View File

@ -15,7 +15,7 @@ end
itest(20) itest(20)
HERE HERE
@should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x44,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x4,0x0,0x0,0xeb,0x2,0x0,0x0,0xea,0x3c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0x0,0x0,0x0,0xeb,0x0,0x80,0xbd,0xe8] @should = [0x0,0x40,0x2d,0xe9,0xc,0x0,0x53,0xe3,0x3,0x0,0x0,0xba,0x34,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd4,0xff,0xff,0xeb,0x2,0x0,0x0,0xea,0x2c,0x20,0x8f,0xe2,0x8,0x30,0xa0,0xe3,0xd0,0xff,0xff,0xeb,0x0,0x80,0xbd,0xe8]
@output = "else " @output = "else "
@target = [:Object , :itest] @target = [:Object , :itest]
parse parse

View File

@ -7,7 +7,7 @@ class TestPutint < MiniTest::Test
@string_input = <<HERE @string_input = <<HERE
42.putint() 42.putint()
HERE HERE
@should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0xa0,0xe1,0x34,0x20,0x8f,0xe2,0x9,0x20,0x82,0xe2,0xe9,0xff,0xff,0xeb,0x28,0x20,0x8f,0xe2,0xc,0x30,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x2,0x10,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x80,0xbd,0xe8] @should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0xa0,0xe1,0x78,0x20,0x8f,0xe2,0x9,0x20,0x82,0xe2,0xe2,0xff,0xff,0xeb,0x6c,0x20,0x8f,0xe2,0xc,0x30,0xa0,0xe3,0x1,0x0,0xa0,0xe3,0x2,0x10,0xa0,0xe1,0x3,0x20,0xa0,0xe1,0x4,0x70,0xa0,0xe3,0x0,0x0,0x0,0xef,0x0,0x80,0xbd,0xe8]
@output = " 42 " @output = " 42 "
@target = [:Object , :putint] @target = [:Object , :putint]
parse parse

View File

@ -20,7 +20,7 @@ end # r0 <- r5
fibonaccit( 10 ) fibonaccit( 10 )
HERE HERE
@should = [0x0,0x40,0x2d,0xe9,0x0,0x40,0xa0,0xe3,0x1,0x50,0xa0,0xe3,0x1,0x0,0x53,0xe3,0x4,0x0,0x0,0xda,0x4,0x60,0xa0,0xe1,0x5,0x40,0xa0,0xe1,0x5,0x50,0x86,0xe0,0x1,0x30,0x43,0xe2,0xf8,0xff,0xff,0xea,0x20,0x0,0x2d,0xe9,0x5,0x20,0xa0,0xe1,0x13,0x0,0x0,0xeb,0x20,0x0,0xbd,0xe8,0x5,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8] @should = [0x0,0x40,0x2d,0xe9,0x0,0x40,0xa0,0xe3,0x1,0x50,0xa0,0xe3,0x1,0x0,0x53,0xe3,0x4,0x0,0x0,0xda,0x4,0x60,0xa0,0xe1,0x5,0x40,0xa0,0xe1,0x5,0x50,0x86,0xe0,0x1,0x30,0x43,0xe2,0xf8,0xff,0xff,0xea,0x20,0x0,0x2d,0xe9,0x5,0x20,0xa0,0xe1,0xd4,0xff,0xff,0xeb,0x20,0x0,0xbd,0xe8,0x5,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]
@output = " 55 " @output = " 55 "
@target = [:Object , :fibonaccit] @target = [:Object , :fibonaccit]
parse parse