first while test working
fixed logic error in test framework
This commit is contained in:
parent
ea882f403a
commit
35a0952943
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user