first while test working

fixed logic error in test framework
This commit is contained in:
Torsten Ruger 2018-03-16 12:33:11 +05:30
parent ea882f403a
commit 35a0952943
9 changed files with 71 additions and 58 deletions

View File

@ -1,10 +1,21 @@
module Mom module Mom
# A base class for conditions in MOM # A base class for conditions in MOM
# Just a marker, no real functionality for now # Checks (if in code, compare in assm) jump or not, depending
# The logic we choose is closer to the code logic (the asm is reversed)
# When we write an if, the true is the next code, so the Check logic is
# that if the check passes, no jump happens
# This means you need to pass the false label, where to jump to if the
# check does not pass
# Note: In assembler a branch on 0 does just that, it branches if the condition
# is met. This means that the asm implementation is somewhat the reverse
# of the Mom names. But it's easier to understand (imho)
class Check < Instruction class Check < Instruction
attr_reader :false_jump
def initialize(false_jump)
@false_jump = false_jump
raise "Jump target must be a label #{false_jump}" unless false_jump.is_a?(Label)
end
end end
# The funny thing about the ruby truth is that is is anything but false or nil # The funny thing about the ruby truth is that is is anything but false or nil
@ -15,8 +26,10 @@ module Mom
class TruthCheck < Check class TruthCheck < Check
attr_reader :condition attr_reader :condition
def initialize(condition) def initialize(condition , false_jump)
super(false_jump)
@condition = condition @condition = condition
raise "condition must be slot_definition #{condition}" unless condition.is_a?(SlotDefinition)
end end
def to_risc(compiler) def to_risc(compiler)

View File

@ -14,9 +14,7 @@ module Vool
def chain_assign(assign , method) def chain_assign(assign , method)
return assign unless @value.is_a?(SendStatement) return assign unless @value.is_a?(SendStatement)
first = @value.to_mom(method) @value.to_mom(method) << assign
first.next = assign
return first
end end
def each(&block) def each(&block)

View File

@ -49,8 +49,8 @@ module Vool
def initialize(type = nil) def initialize(type = nil)
@my_type = type @my_type = type
end end
def to_mom(in_method) def slot_definition(in_method)
@clazz = in_method.clazz @my_type = in_method.for_type
Mom::SlotDefinition.new(:message , [:receiver]) Mom::SlotDefinition.new(:message , [:receiver])
end end
def ct_type def ct_type

View File

@ -4,7 +4,7 @@ module Vool
def initialize( name , args , body , clazz = nil) def initialize( name , args , body , clazz = nil)
@name , @args , @body = name , args , body @name , @args , @body = name , args , body
raise "no bod" unless body raise "no bod" unless @body
@clazz = clazz @clazz = clazz
end end

View File

@ -46,6 +46,12 @@ module Vool
end end
end end
# When used as right hand side, this tells what data to move to get the result into
# a varaible. It is (off course) the return value of the message
def slot_definition(in_method)
Mom::SlotDefinition.new(:message ,[ :return_value])
end
def message_setup(in_method) def message_setup(in_method)
setup = Mom::MessageSetup.new(in_method) << setup = Mom::MessageSetup.new(in_method) <<
Mom::SlotLoad.new([:message , :next_message , :receiver] , @receiver.slot_definition(in_method)) Mom::SlotLoad.new([:message , :next_message , :receiver] , @receiver.slot_definition(in_method))

View File

@ -28,7 +28,7 @@ module Vool
self self
end end
# create machine instructions # create mom instructions
def to_mom( method ) def to_mom( method )
raise "Empty list ? #{statements.length}" unless @statements[0] raise "Empty list ? #{statements.length}" unless @statements[0]
flat = @statements.shift.to_mom(method) flat = @statements.shift.to_mom(method)
@ -48,13 +48,21 @@ module Vool
end end
def normalize def normalize
if( single? )
first.normalize
else
Statements.new(@statements.collect{|s| s.normalize}) Statements.new(@statements.collect{|s| s.normalize})
end end
end end
end
class ScopeStatement < Statements class ScopeStatement < Statements
def normalize def normalize
if( single? )
first.normalize
else
ScopeStatement.new(@statements.collect{|s| s.normalize}) ScopeStatement.new(@statements.collect{|s| s.normalize})
end end
end end
end end
end

View File

@ -3,49 +3,34 @@ require_relative "normalizer"
module Vool module Vool
class WhileStatement < Statement class WhileStatement < Statement
include Normalizer include Normalizer
attr_reader :condition , :statements attr_reader :condition , :body
def initialize( condition , statements ) def initialize( condition , body )
@condition = condition @condition = condition
@statements = statements @body = body
simplify_condition
end end
def normalize(method) def normalize
cond , rest = *normalize_name(@condition) cond , rest = *normalize_name(@condition.normalize)
me = WhileStatement.new(cond , @statements.normalize(method)) me = WhileStatement.new(cond , @body.normalize)
return me unless rest return me unless rest
rest << me rest << me
rest
end end
def to_mom( method ) def to_mom( method )
statements = @statements.to_mom( method ) merge_label = Mom::Label.new( "merge_label_#{object_id}")
condition , hoisted = hoist_condition( method ) cond_label = Mom::Label.new( "cond_label_#{object_id}")
cond = Mom::TruthCheck.new(condition.to_mom(method)) cond_label << Mom::TruthCheck.new(condition.slot_definition(method) , merge_label)
check = Mom::WhileStatement.new( cond , statements ) cond_label << @body.to_mom(method)
check.hoisted = hoisted.to_mom(method) if hoisted cond_label << Mom::Jump.new(cond_label)
check cond_label << merge_label
end end
def flatten(options = {}) def each(&block)
merge_label = Label.new( "merge_label_#{object_id}") block.call(self)
cond_label = Label.new( "cond_label_#{object_id}") @condition.each(&block)
@nekst = cond_label @body.each(&block)
@nekst.append(hoisted.flatten) if hoisted
@nekst.append condition.flatten( true_label: cond_label , false_label: merge_label)
@nekst.append merge_label
@nekst
end
def simplify_condition
return unless @condition.is_a?(ScopeStatement)
@condition = @condition.first if @condition.single?
end
def collect(arr)
@condition.collect(arr)
@statements.collect(arr)
super
end end
end end

View File

@ -22,11 +22,13 @@ module MomCompile
include CompilerHelper include CompilerHelper
def compile_first_method input def compile_first_method input
lst = Vool::VoolCompiler.ruby_to_vool as_test_main( input ) # works a lot like Vool.ruby_to_vool
assert_equal Parfait::Class , lst.clazz.class , lst statements = Vool::RubyCompiler.compile as_test_main( input )
@method = lst.clazz.get_method(:main) statements = statements.normalize
res = statements.create_objects
assert_equal Parfait::Class , statements.clazz.class , statements
@method = statements.clazz.get_method(:main)
assert_equal Parfait::VoolMethod , @method.class assert_equal Parfait::VoolMethod , @method.class
res = lst.create_objects
#puts "#{res.class}" #puts "#{res.class}"
res res
end end

View File

@ -4,24 +4,25 @@ require_relative "helper"
module Vool module Vool
class TestWhileConditionMom < MiniTest::Test class TestWhileConditionMom < MiniTest::Test
include MomCompile include MomCompile
include Mom
def setup def setup
Risc.machine.boot Risc.machine.boot
@stats = compile_first_method( "while(@a == 5) ; 5.mod4 ; end") @ins = compile_first_method( "while(5.mod4) ; 5.mod4 ; end")
@first = @stats.first
end end
def test_if_compiles_as_array def test_condition_compiles_to_check
assert_equal Mom::WhileStatement , @first.class , @stats assert_equal TruthCheck , @ins.next(6).class
end
def test_condition_compiles_to_slot
assert_equal Mom::TruthCheck , @first.condition.class
end end
def test_condition_is_slot def test_condition_is_slot
assert_equal Mom::SlotDefinition , @first.condition.condition.class , @stats assert_equal SlotDefinition , @ins.next(6).condition.class , @ins
end end
def test_hoisetd def test_hoisetd
assert_equal Mom::SlotLoad , @first.hoisted.class assert_equal MessageSetup , @ins.class
end end
def test_array
check_array [MessageSetup,SlotLoad,ArgumentTransfer,SimpleCall,SlotLoad,Label,TruthCheck,MessageSetup,SlotLoad,ArgumentTransfer,SimpleCall,Jump,Label] , @ins
end
end end
end end