fixing and testing operators
This commit is contained in:
parent
e436581ce8
commit
3d83f203ca
@ -184,7 +184,7 @@ module Interpreter
|
|||||||
rr = @instruction.right
|
rr = @instruction.right
|
||||||
right = get_register(rr)
|
right = get_register(rr)
|
||||||
case @instruction.operator.to_s
|
case @instruction.operator.to_s
|
||||||
when "add"
|
when "+"
|
||||||
result = left + right
|
result = left + right
|
||||||
when "/"
|
when "/"
|
||||||
result = left / right
|
result = left / right
|
||||||
@ -198,7 +198,7 @@ module Interpreter
|
|||||||
raise "unimplemented '#{@instruction.operator}' #{@instruction}"
|
raise "unimplemented '#{@instruction.operator}' #{@instruction}"
|
||||||
end
|
end
|
||||||
puts "#{@instruction} == #{result}"
|
puts "#{@instruction} == #{result}"
|
||||||
right = set_register(rr , result)
|
right = set_register(@instruction.left , result)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ module Parfait
|
|||||||
def initialize type , name , value = nil
|
def initialize type , name , value = nil
|
||||||
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type)
|
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type)
|
||||||
self.type , self.name , self.value = type , name , value
|
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
|
raise "must give name for variable" unless name
|
||||||
end
|
end
|
||||||
attributes [:type , :name, :value]
|
attributes [:type , :name, :value]
|
||||||
|
@ -11,7 +11,7 @@ module Phisol
|
|||||||
when :self
|
when :self
|
||||||
index = @clazz.object_layout.variable_index(field_name)
|
index = @clazz.object_layout.variable_index(field_name)
|
||||||
raise "field access, but no such field:#{field_name} for class #{@clazz.name}" unless index
|
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 )
|
move = Register.get_slot(statement, :self , index , value )
|
||||||
@method.source.add_code move
|
@method.source.add_code move
|
||||||
return value
|
return value
|
||||||
|
@ -4,23 +4,15 @@ module Phisol
|
|||||||
def on_operator_value statement
|
def on_operator_value statement
|
||||||
puts "operator #{statement.inspect}"
|
puts "operator #{statement.inspect}"
|
||||||
operator , left_e , right_e = *statement
|
operator , left_e , right_e = *statement
|
||||||
left_slot = process(left_e)
|
# left and right must be expressions. Expressions return a register when compiled
|
||||||
right_slot = process(right_e)
|
left_reg = process(left_e)
|
||||||
puts "left #{left_slot}"
|
right_reg = process(right_e)
|
||||||
puts "right #{right_slot}"
|
raise "Not register #{left_reg}" unless left_reg.is_a?(Register::RegisterValue)
|
||||||
tmp1 = use_reg :int
|
raise "Not register #{right_reg}" unless right_reg.is_a?(Register::RegisterValue)
|
||||||
tmp2 = use_reg :int
|
puts "left #{left_reg}"
|
||||||
get = Register.get_slot_to(statement , left_slot , tmp1 )
|
puts "right #{right_reg}"
|
||||||
get2 = Register.get_slot_to(statement , right_slot , tmp2 )
|
@method.source.add_code Register::OperatorInstruction.new(statement,operator,left_reg,right_reg)
|
||||||
puts "GET #{get}"
|
return left_reg # though this has wrong value attached
|
||||||
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 )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_assignment statement
|
def on_assignment statement
|
||||||
|
@ -49,15 +49,17 @@ module Register
|
|||||||
# This relies on linux to save and restore all registers
|
# This relies on linux to save and restore all registers
|
||||||
#
|
#
|
||||||
def save_message(function)
|
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
|
end
|
||||||
|
|
||||||
def restore_message(function)
|
def restore_message(function)
|
||||||
|
r8 = RegisterValue.new( :r8 , :Message)
|
||||||
return_tmp = Register.tmp_reg function.source.return_type
|
return_tmp = Register.tmp_reg function.source.return_type
|
||||||
# get the sys return out of the way
|
# get the sys return out of the way
|
||||||
function.source.add_code RegisterTransfer.new(function, Register.message_reg , return_tmp )
|
function.source.add_code RegisterTransfer.new(function, Register.message_reg , return_tmp )
|
||||||
# load the stored message into the base RegisterMachine
|
# 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
|
# save the return value into the message
|
||||||
function.source.add_code Register.set_slot( function, return_tmp , :message , :return_value )
|
function.source.add_code Register.set_slot( function, return_tmp , :message , :return_value )
|
||||||
# and "unroll" self and frame
|
# and "unroll" self and frame
|
||||||
|
@ -30,12 +30,6 @@ module Register
|
|||||||
def assigns
|
def assigns
|
||||||
raise "abstract called for #{self.class}"
|
raise "abstract called for #{self.class}"
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -18,8 +18,10 @@ module Register
|
|||||||
# Note: this may be reversed from some assembler notations (also arm)
|
# Note: this may be reversed from some assembler notations (also arm)
|
||||||
def initialize source , from , to
|
def initialize source , from , to
|
||||||
super(source)
|
super(source)
|
||||||
@from = wrap_register(from,:int)
|
@from = from
|
||||||
@to = wrap_register(to,:int)
|
@to = to
|
||||||
|
raise "Fix me #{from}" unless from.is_a? RegisterValue
|
||||||
|
raise "Fix me #{to}" unless to.is_a? RegisterValue
|
||||||
end
|
end
|
||||||
attr_reader :from, :to
|
attr_reader :from, :to
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ module Register
|
|||||||
raise "wrong type for register init #{r}" unless r.is_a? Symbol
|
raise "wrong type for register init #{r}" unless r.is_a? Symbol
|
||||||
raise "double r #{r}" if r.to_s[0,1] == "rr"
|
raise "double r #{r}" if r.to_s[0,1] == "rr"
|
||||||
raise "not reg #{r}" unless self.class.look_like_reg r
|
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
|
@type = type
|
||||||
@symbol = r
|
@symbol = r
|
||||||
@value = value
|
@value = value
|
||||||
@ -39,10 +40,10 @@ module Register
|
|||||||
end
|
end
|
||||||
|
|
||||||
#helper method to calculate with register symbols
|
#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
|
int = @symbol[1,3].to_i
|
||||||
sym = "r#{int + 1}".to_sym
|
sym = "r#{int + 1}".to_sym
|
||||||
RegisterValue.new( sym , type)
|
RegisterValue.new( sym , type, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sof_reference_name
|
def sof_reference_name
|
||||||
|
45
test/compiler/expressions/test_ops.rb
Normal file
45
test/compiler/expressions/test_ops.rb
Normal 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
|
Loading…
Reference in New Issue
Block a user