diff --git a/test/typed/method_compiler/helper.rb b/test/typed/method_compiler/helper.rb index 5488691e..8aedfbde 100644 --- a/test/typed/method_compiler/helper.rb +++ b/test/typed/method_compiler/helper.rb @@ -1,63 +1,65 @@ require_relative '../helper' -module ExpressionHelper +module Register + module ExpressionHelper - def check - Register.machine.boot unless Register.machine.booted - compiler = Typed::MethodCompiler.new Parfait.object_space.get_main - code = Typed.ast_to_code @input - assert code.to_s , @input - produced = compiler.process( code ) - assert @output , "No output given" - assert_equal produced.class , @output , "Wrong class" - produced - end - - # test hack to in place change object type - def add_space_field(name,type) - class_type = Parfait.object_space.get_class_by_name(:Space).instance_type - class_type.send(:private_add_instance_variable, name , type) - end -end - -module Statements - include AST::Sexp - include Compiling - - def setup - Register.machine.boot # force boot to reset main - end - - - def check - assert @expect , "No output given" - compiler = Typed::MethodCompiler.new - code = Typed.ast_to_code( @input ) - assert code.to_s , @input - produced = compiler.process( code ) - produced = Parfait.object_space.get_main.instructions - compare_instructions produced , @expect - produced - end - - def compare_instructions instruction , expect - index = 0 - start = instruction - begin - should = expect[index] - assert should , "No instruction at #{index}" - assert_equal instruction.class , should , "Expected at #{index+1}\n#{should(start)}" - index += 1 - instruction = instruction.next - end while( instruction ) - end - def should start - str = start.to_ac.to_s - str.gsub!("Register::","") - ret = "" - str.split(",").each_slice(7).each do |line| - ret += " " + line.join(",") + " ,\n" + def check + Register.machine.boot unless Register.machine.booted + compiler = Typed::MethodCompiler.new Parfait.object_space.get_main + code = Typed.ast_to_code @input + assert code.to_s , @input + produced = compiler.process( code ) + assert @output , "No output given" + assert_equal produced.class , @output , "Wrong class" + produced + end + + # test hack to in place change object type + def add_space_field(name,type) + class_type = Parfait.object_space.get_class_by_name(:Space).instance_type + class_type.send(:private_add_instance_variable, name , type) + end + end + + module Statements + include AST::Sexp + include Compiling + + def setup + Register.machine.boot # force boot to reset main + end + + + def check + assert @expect , "No output given" + compiler = Typed::MethodCompiler.new + code = Typed.ast_to_code( @input ) + assert code.to_s , @input + produced = compiler.process( code ) + produced = Parfait.object_space.get_main.instructions + compare_instructions produced , @expect + produced + end + + def compare_instructions instruction , expect + index = 0 + start = instruction + begin + should = expect[index] + assert should , "No instruction at #{index}" + assert_equal instruction.class , should , "Expected at #{index+1}\n#{should(start)}" + index += 1 + instruction = instruction.next + end while( instruction ) + end + def should start + str = start.to_ac.to_s + str.gsub!("Register::","") + ret = "" + str.split(",").each_slice(7).each do |line| + ret += " " + line.join(",") + " ,\n" + end + ret end - ret end end diff --git a/test/typed/method_compiler/test_assignment.rb b/test/typed/method_compiler/test_assignment.rb index 66c9f5b7..9ffdb505 100644 --- a/test/typed/method_compiler/test_assignment.rb +++ b/test/typed/method_compiler/test_assignment.rb @@ -1,100 +1,100 @@ require_relative 'helper' module Register -class TestAssignStatement < MiniTest::Test - include Statements + class TestAssignStatement < MiniTest::Test + include Statements - def test_assign_op - Parfait.object_space.get_main.add_local(:r , :Integer) + def test_assign_op + Parfait.object_space.get_main.add_local(:r , :Integer) - @input = s(:statements, s(:assignment, s(:name, :r), s(:operator_value, :+, s(:int, 10), s(:int, 1)))) + @input = s(:statements, s(:assignment, s(:name, :r), s(:operator_value, :+, s(:int, 10), s(:int, 1)))) - @expect = [Label, LoadConstant, LoadConstant, OperatorInstruction, SlotToReg, RegToSlot, Label , - FunctionReturn] - check - end - - def test_assign_local - Parfait.object_space.get_main.add_local(:r , :Integer) - @input =s(:statements, s(:assignment, s(:name, :r), s(:int, 5))) - - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - check - end - - def test_assign_local_assign - Parfait.object_space.get_main.add_local(:r , :Integer) - - @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5))) - - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - check - end - - def test_assign_call - Parfait.object_space.get_main.add_local(:r , :Integer) - @input = s(:statements, s(:assignment, s(:name, :r), s(:call, s(:name, :main), s(:arguments)))) - @expect = [Label, SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, LoadConstant , - SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer, FunctionCall , - Label, RegisterTransfer, SlotToReg, SlotToReg, SlotToReg, RegToSlot, Label , + @expect = [Label, LoadConstant, LoadConstant, OperatorInstruction, SlotToReg, RegToSlot, Label , FunctionReturn] + check + end + + def test_assign_local + Parfait.object_space.get_main.add_local(:r , :Integer) + @input =s(:statements, s(:assignment, s(:name, :r), s(:int, 5))) + + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] + check + end + + def test_assign_local_assign + Parfait.object_space.get_main.add_local(:r , :Integer) + + @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5))) + + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] check - end + end - def test_named_list_get - Parfait.object_space.get_main.add_local(:r , :Integer) - @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5)), s(:return, s(:name, :r))) - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot , - Label, FunctionReturn] - was = check - get = was.next(5) - assert_equal SlotToReg , get.class - assert_equal 1 + 1, get.index , "Get to named_list index must be offset, not #{get.index}" - end + def test_assign_call + Parfait.object_space.get_main.add_local(:r , :Integer) + @input = s(:statements, s(:assignment, s(:name, :r), s(:call, s(:name, :main), s(:arguments)))) + @expect = [Label, SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, LoadConstant , + SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer, FunctionCall , + Label, RegisterTransfer, SlotToReg, SlotToReg, SlotToReg, RegToSlot, Label , + FunctionReturn] + check + end - def test_assign_local_int - Parfait.object_space.get_main.add_local(:r , :Integer) - @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5)) ) - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - was = check - set = was.next(3) - assert_equal RegToSlot , set.class - assert_equal 1 + 1, set.index , "Set to named_list index must be offset, not #{set.index}" - end + def test_named_list_get + Parfait.object_space.get_main.add_local(:r , :Integer) + @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5)), s(:return, s(:name, :r))) + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, SlotToReg, SlotToReg, RegToSlot , + Label, FunctionReturn] + was = check + get = was.next(5) + assert_equal SlotToReg , get.class + assert_equal 1 + 1, get.index , "Get to named_list index must be offset, not #{get.index}" + end - def test_misassign_local - Parfait.object_space.get_main.add_local(:r , :Integer) - @input = s(:statements, s(:assignment, s(:name, :r), s(:string, "5")) ) - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - assert_raises {check } - end + def test_assign_local_int + Parfait.object_space.get_main.add_local(:r , :Integer) + @input = s(:statements, s(:assignment, s(:name, :r), s(:int, 5)) ) + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] + was = check + set = was.next(3) + assert_equal RegToSlot , set.class + assert_equal 1 + 1, set.index , "Set to named_list index must be offset, not #{set.index}" + end - def test_assign_arg - Parfait.object_space.get_main.add_argument(:blar , :Integer) - @input = s(:statements, s(:assignment, s(:name, :blar), s(:int, 5))) - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - was = check - set = was.next(3) - assert_equal RegToSlot , set.class - assert_equal 1 + 1, set.index , "Set to args index must be offset, not #{set.index}" - end + def test_misassign_local + Parfait.object_space.get_main.add_local(:r , :Integer) + @input = s(:statements, s(:assignment, s(:name, :r), s(:string, "5")) ) + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] + assert_raises {check } + end - def test_misassign_arg - Parfait.object_space.get_main.add_argument(:blar , :Integer) - @input = s(:statements, s(:assignment, s(:name, :blar), s(:string, "5"))) - @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] - assert_raises {check } - end + def test_assign_arg + Parfait.object_space.get_main.add_argument(:blar , :Integer) + @input = s(:statements, s(:assignment, s(:name, :blar), s(:int, 5))) + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] + was = check + set = was.next(3) + assert_equal RegToSlot , set.class + assert_equal 1 + 1, set.index , "Set to args index must be offset, not #{set.index}" + end - def test_arg_get - # have to define bar externally, just because redefining main. Otherwise that would be automatic - Parfait.object_space.get_main.add_argument(:balr , :Integer) - @input = s(:statements, s(:return, s(:name, :balr))) - @expect = [Label, SlotToReg, SlotToReg, RegToSlot, Label, FunctionReturn] - was = check - get = was.next(2) - assert_equal SlotToReg , get.class - assert_equal 1 + 1, get.index , "Get to args index must be offset, not #{get.index}" + def test_misassign_arg + Parfait.object_space.get_main.add_argument(:blar , :Integer) + @input = s(:statements, s(:assignment, s(:name, :blar), s(:string, "5"))) + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn] + assert_raises {check } + end + + def test_arg_get + # have to define bar externally, just because redefining main. Otherwise that would be automatic + Parfait.object_space.get_main.add_argument(:balr , :Integer) + @input = s(:statements, s(:return, s(:name, :balr))) + @expect = [Label, SlotToReg, SlotToReg, RegToSlot, Label, FunctionReturn] + was = check + get = was.next(2) + assert_equal SlotToReg , get.class + assert_equal 1 + 1, get.index , "Get to args index must be offset, not #{get.index}" + end end end -end diff --git a/test/typed/method_compiler/test_basic_values.rb b/test/typed/method_compiler/test_basic_values.rb index 72c6b3fc..3eeb97e8 100644 --- a/test/typed/method_compiler/test_basic_values.rb +++ b/test/typed/method_compiler/test_basic_values.rb @@ -1,39 +1,41 @@ require_relative "helper" +module Register -class TestBasic < MiniTest::Test - include ExpressionHelper - include AST::Sexp + class TestBasic < MiniTest::Test + include ExpressionHelper + include AST::Sexp - def setup - Register.machine.boot - @output = Register::RegisterValue - end + def setup + Register.machine.boot + @output = Register::RegisterValue + end - def test_number - @input = s(:int , 42) - assert_equal 42 , check.value - end + def test_number + @input = s(:int , 42) + assert_equal 42 , check.value + end - def test_true - @input = s(:true) - check - end - def test_false - @input = s(:false) - check - end - def test_nil - @input = s(:nil) - check - end - def test_self - @input = s(:name, :self) - check - end - def test_string - @input = s(:string , "hello") - check - end + def test_true + @input = s(:true) + check + end + def test_false + @input = s(:false) + check + end + def test_nil + @input = s(:nil) + check + end + def test_self + @input = s(:name, :self) + check + end + def test_string + @input = s(:string , "hello") + check + end + end end diff --git a/test/typed/method_compiler/test_call_site.rb b/test/typed/method_compiler/test_call_site.rb index e2fb9702..05513efe 100644 --- a/test/typed/method_compiler/test_call_site.rb +++ b/test/typed/method_compiler/test_call_site.rb @@ -2,70 +2,70 @@ require_relative 'helper' require_relative "test_call_expression" module Register -class TestCallStatement < MiniTest::Test - include Statements + class TestCallStatement < MiniTest::Test + include Statements - def test_call_constant_int - clean_compile :Integer, :puti, {}, s(:statements, s(:return, s(:int, 1))) - @input = s(:call, s(:name, :puti), s(:arguments), s(:receiver, s(:int, 42))) - @expect = [Label, SlotToReg, LoadConstant, RegToSlot, LoadConstant, RegToSlot, LoadConstant , - SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer, FunctionCall , - Label, RegisterTransfer, SlotToReg, SlotToReg, Label, FunctionReturn] + def test_call_constant_int + clean_compile :Integer, :puti, {}, s(:statements, s(:return, s(:int, 1))) + @input = s(:call, s(:name, :puti), s(:arguments), s(:receiver, s(:int, 42))) + @expect = [Label, SlotToReg, LoadConstant, RegToSlot, LoadConstant, RegToSlot, LoadConstant , + SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer, FunctionCall , + Label, RegisterTransfer, SlotToReg, SlotToReg, Label, FunctionReturn] + check + end + + + def test_call_constant_string + clean_compile :Word, :putstr,{}, s(:statements, s(:return, s(:int, 1))) + + @input =s(:call, s(:name, :putstr), s(:arguments), s(:receiver, s(:string, "Hello"))) + @expect = [Label, SlotToReg, LoadConstant, RegToSlot, LoadConstant, RegToSlot, LoadConstant , + SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer, FunctionCall , + Label, RegisterTransfer, SlotToReg, SlotToReg, Label, FunctionReturn] + check + end + + def _test_call_local_int + Parfait.object_space.get_main.add_local(:testi , :Integer) + clean_compile :Integer, :putint, {}, s(:statements, s(:return, s(:int, 1))) + @input = s(:statements, s(:assignment, s(:name, :testi), s(:int, 20)), s(:call, s(:name, :putint), s(:arguments), s(:receiver, s(:name, :testi)))) + + @expect = [Label, LoadConstant, SlotToReg, RegToSlot, SlotToReg, SlotToReg, SlotToReg , + RegToSlot, LoadConstant, RegToSlot, LoadConstant, RegToSlot, LoadConstant, RegToSlot , + RegisterTransfer, FunctionCall, Label, RegisterTransfer, SlotToReg, SlotToReg, Label , + FunctionReturn] check + end + + def test_call_local_class + Parfait.object_space.get_main.add_local(:test_l , :List) + clean_compile :List, :add, {}, s(:statements, s(:return, s(:int, 1))) + + @input =s(:statements, s(:call, s(:name, :add), s(:arguments), s(:receiver, s(:name, :test_l)))) + @expect = [Label, SlotToReg, SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot , + LoadConstant, SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RegisterTransfer , + FunctionCall, Label, RegisterTransfer, SlotToReg, SlotToReg, Label, FunctionReturn] + check + end + + def _test_call_puts + @input = <