fixing and testing operators

This commit is contained in:
Torsten Ruger 2015-10-15 09:32:47 +03:00
parent e436581ce8
commit 3d83f203ca
9 changed files with 69 additions and 33 deletions

View File

@ -184,7 +184,7 @@ module Interpreter
rr = @instruction.right
right = get_register(rr)
case @instruction.operator.to_s
when "add"
when "+"
result = left + right
when "/"
result = left / right
@ -198,7 +198,7 @@ module Interpreter
raise "unimplemented '#{@instruction.operator}' #{@instruction}"
end
puts "#{@instruction} == #{result}"
right = set_register(rr , result)
right = set_register(@instruction.left , result)
true
end
end

View File

@ -4,7 +4,7 @@ module Parfait
def initialize type , name , value = nil
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type)
self.type , self.name , self.value = type , name , value
self.value = 0 if self.type == :int and value == nil
self.value = 0 if self.type == :Integer and value == nil
raise "must give name for variable" unless name
end
attributes [:type , :name, :value]

View File

@ -11,7 +11,7 @@ module Phisol
when :self
index = @clazz.object_layout.variable_index(field_name)
raise "field access, but no such field:#{field_name} for class #{@clazz.name}" unless index
value = use_reg(:int) #TODO, need types in layout
value = use_reg(:Integer) #TODO, need types in layout
move = Register.get_slot(statement, :self , index , value )
@method.source.add_code move
return value

View File

@ -4,23 +4,15 @@ module Phisol
def on_operator_value statement
puts "operator #{statement.inspect}"
operator , left_e , right_e = *statement
left_slot = process(left_e)
right_slot = process(right_e)
puts "left #{left_slot}"
puts "right #{right_slot}"
tmp1 = use_reg :int
tmp2 = use_reg :int
get = Register.get_slot_to(statement , left_slot , tmp1 )
get2 = Register.get_slot_to(statement , right_slot , tmp2 )
puts "GET #{get}"
puts "GET2 #{get2}"
@method.source.add_code get
@method.source.add_code get2
@method.source.add_code Register::OperatorInstruction.new(statement,operator, tmp1,tmp2)
release_reg tmp2
release_reg tmp1
Virtual::Return.new(:int )
# left and right must be expressions. Expressions return a register when compiled
left_reg = process(left_e)
right_reg = process(right_e)
raise "Not register #{left_reg}" unless left_reg.is_a?(Register::RegisterValue)
raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue)
puts "left #{left_reg}"
puts "right #{right_reg}"
@method.source.add_code Register::OperatorInstruction.new(statement,operator,left_reg,right_reg)
return left_reg # though this has wrong value attached
end
def on_assignment statement

View File

@ -49,15 +49,17 @@ module Register
# This relies on linux to save and restore all registers
#
def save_message(function)
function.source.add_code RegisterTransfer.new(function, Register.message_reg , :r8 )
r8 = RegisterValue.new( :r8 , :Message)
function.source.add_code RegisterTransfer.new(function, Register.message_reg , r8 )
end
def restore_message(function)
r8 = RegisterValue.new( :r8 , :Message)
return_tmp = Register.tmp_reg function.source.return_type
# get the sys return out of the way
function.source.add_code RegisterTransfer.new(function, Register.message_reg , return_tmp )
# load the stored message into the base RegisterMachine
function.source.add_code RegisterTransfer.new(function, :r8 , Register.message_reg )
function.source.add_code RegisterTransfer.new(function, r8 , Register.message_reg )
# save the return value into the message
function.source.add_code Register.set_slot( function, return_tmp , :message , :return_value )
# and "unroll" self and frame

View File

@ -30,12 +30,6 @@ module Register
def assigns
raise "abstract called for #{self.class}"
end
# wrap symbols into regsiter reference if needed
def wrap_register reg , type
return reg if reg.is_a? RegisterValue
RegisterValue.new(reg , type)
end
end
end

View File

@ -18,8 +18,10 @@ module Register
# Note: this may be reversed from some assembler notations (also arm)
def initialize source , from , to
super(source)
@from = wrap_register(from,:int)
@to = wrap_register(to,:int)
@from = from
@to = to
raise "Fix me #{from}" unless from.is_a? RegisterValue
raise "Fix me #{to}" unless to.is_a? RegisterValue
end
attr_reader :from, :to

View File

@ -10,6 +10,7 @@ module Register
raise "wrong type for register init #{r}" unless r.is_a? Symbol
raise "double r #{r}" if r.to_s[0,1] == "rr"
raise "not reg #{r}" unless self.class.look_like_reg r
raise "Legacy type error, should be class" if (type == :int) or (type == :ref)
@type = type
@symbol = r
@value = value
@ -39,10 +40,10 @@ module Register
end
#helper method to calculate with register symbols
def next_reg_use type
def next_reg_use type , value = nil
int = @symbol[1,3].to_i
sym = "r#{int + 1}".to_sym
RegisterValue.new( sym , type)
RegisterValue.new( sym , type, value)
end
def sof_reference_name

View File

@ -0,0 +1,45 @@
require_relative "compiler_helper"
module Virtual
class TestOps < MiniTest::Test
include CompilerHelper
def setup
Virtual.machine.boot
@root = :operator_value
@output = Register::RegisterValue
end
def operators
["+" , "-" , "*" , "/" , "=="]
end
def test_ints
operators.each do |op|
@string_input = '2 + 3'.sub("+" , op)
check
end
end
def test_local_int
Virtual.machine.space.get_main.ensure_local(:bar , :Integer)
@string_input = 'bar + 3'
check
end
def test_int_local
Virtual.machine.space.get_main.ensure_local(:bar , :Integer)
@string_input = '3 + bar'
check
end
def test_field_int
Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro)
@string_input = "self.bro + 3"
check
end
def test_int_field
Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro)
@string_input = "3 + self.bro"
check
end
end
end