starting to_risc descent
just fleshing it for now
This commit is contained in:
parent
b297650b78
commit
96800fd8fd
@ -16,6 +16,9 @@ module Mom
|
||||
def initialize(name)
|
||||
@name = name
|
||||
end
|
||||
def to_risc(compiler)
|
||||
Risc::Label.new(self,name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -16,6 +16,11 @@ module Mom
|
||||
def initialize(method)
|
||||
@method = method
|
||||
end
|
||||
|
||||
def to_risc(compiler)
|
||||
Risc::Label.new(self,method.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -12,5 +12,9 @@ module Mom
|
||||
def initialize(left, right)
|
||||
@left , @right = left , right
|
||||
end
|
||||
|
||||
def to_risc(compiler)
|
||||
Risc::Label.new(self,"nosense")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -33,6 +33,11 @@ module Mom
|
||||
raise "left not SlotDefinition, #{left}" unless left.is_a? SlotDefinition
|
||||
# raise "right not Mom, #{right.to_rxf}" unless right.class.name.include?("Mom")
|
||||
end
|
||||
|
||||
def to_risc(compiler)
|
||||
Risc::Label.new(self,"nosense")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# A SlotConstant moves a constant into a known Slot.
|
||||
@ -52,6 +57,9 @@ module Mom
|
||||
|
||||
#SlotMove is a SlotLoad where the right side is a slot, just like the left.
|
||||
class SlotMove < SlotLoad
|
||||
def to_risc(compiler)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
class SlotDefinition
|
||||
|
@ -1,5 +1,6 @@
|
||||
module Mom
|
||||
class Statement
|
||||
include Common::List
|
||||
# flattening will change the structure from a tree to a linked list (and use
|
||||
# nekst to do so)
|
||||
def flatten(options = {})
|
||||
@ -18,6 +19,12 @@ module Mom
|
||||
flat
|
||||
end
|
||||
|
||||
def initialize(arr)
|
||||
super(arr)
|
||||
arr.each {|s|
|
||||
raise "Not a Statement #{s}" unless s.is_a?( Statement) or s.is_a?(Instruction)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -18,5 +18,10 @@ module Mom
|
||||
def initialize(condition)
|
||||
@condition = condition
|
||||
end
|
||||
|
||||
def to_risc(compiler)
|
||||
Risc::Label.new(self,"nosense")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -11,13 +11,13 @@ module Mom
|
||||
end
|
||||
|
||||
def flatten(options = {})
|
||||
cond_label = Label.new( "cond_label_#{object_id}")
|
||||
head = cond_label
|
||||
head.append hoisted.flatten
|
||||
merge_label = Label.new( "merge_label_#{object_id}")
|
||||
head.append condition.flatten( true_label: cond_label , false_label: merge_label)
|
||||
head.append merge_label
|
||||
head
|
||||
cond_label = Label.new( "cond_label_#{object_id}")
|
||||
@nekst = cond_label
|
||||
@nekst.append(hoisted.flatten) if hoisted
|
||||
@nekst.append condition.flatten( true_label: cond_label , false_label: merge_label)
|
||||
@nekst.append merge_label
|
||||
@nekst
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -18,7 +18,7 @@ module Risc
|
||||
@source = source
|
||||
@next = nekst
|
||||
return unless source
|
||||
raise "Source must be string or ast node, not #{source.class}" unless source.is_a?(String) or source.is_a?(Vm::Code)
|
||||
raise "Source must be string or ast node, not #{source.class}" unless source.is_a?(String) or source.is_a?(Mom::Instruction)
|
||||
end
|
||||
attr_reader :source
|
||||
|
||||
|
@ -33,14 +33,10 @@ module Vool
|
||||
locals_type = make_locals
|
||||
method = Parfait::VoolMethod.new(name , args_type , locals_type , body )
|
||||
@clazz.add_method( method )
|
||||
end
|
||||
|
||||
def compile_methods(clazz , methods)
|
||||
methods.each do |method|
|
||||
code = Passes::MethodCompiler.new(method).get_code
|
||||
typed_method = method.create_parfait_method(clazz.instance_type)
|
||||
Risc::MethodCompiler.new( typed_method ).init_method.process( code )
|
||||
end
|
||||
typed_method = method.create_parfait_method(clazz.instance_type)
|
||||
compiler = Risc::MethodCompiler.new( typed_method ).init_method
|
||||
head = @body.to_mom( method ).flatten
|
||||
head.to_risc(compiler)
|
||||
end
|
||||
|
||||
private
|
||||
|
81
test/mom/to_risc/helper.rb
Normal file
81
test/mom/to_risc/helper.rb
Normal file
@ -0,0 +1,81 @@
|
||||
require_relative '../helper'
|
||||
|
||||
module Risc
|
||||
module SpaceHack
|
||||
# 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 ExpressionHelper
|
||||
include SpaceHack
|
||||
|
||||
def check
|
||||
Risc.machine.boot unless Risc.machine.booted
|
||||
compiler = Vm::MethodCompiler.new Parfait.object_space.get_main
|
||||
code = Vm.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
|
||||
|
||||
end
|
||||
|
||||
module Statements
|
||||
include AST::Sexp
|
||||
include CleanCompile
|
||||
include SpaceHack
|
||||
|
||||
def setup
|
||||
Risc.machine.boot # force boot to reset main
|
||||
end
|
||||
|
||||
def preamble
|
||||
[Label, SlotToReg , LoadConstant, RegToSlot, LoadConstant,RegToSlot, LoadConstant, SlotToReg, SlotToReg ]
|
||||
end
|
||||
def postamble
|
||||
[ Label, FunctionReturn]
|
||||
end
|
||||
def check_nil
|
||||
assert @expect , "No output given"
|
||||
|
||||
Vool::VoolCompiler.ruby_to_vool "class Space; def main(arg);#{@input};end;end"
|
||||
|
||||
produced = Parfait.object_space.get_main.instructions
|
||||
compare_instructions produced , @expect
|
||||
end
|
||||
def check_return
|
||||
was = check_nil
|
||||
raise was if was
|
||||
Parfait.object_space.get_main.instructions
|
||||
end
|
||||
|
||||
def compare_instructions( instruction , expect )
|
||||
index = 0
|
||||
all = instruction.to_arr
|
||||
full_expect = preamble + expect + postamble
|
||||
full_expect = expect
|
||||
begin
|
||||
should = full_expect[index]
|
||||
return "No instruction at #{index}" unless should
|
||||
return "Expected at #{index+1}\n#{should(all)}" unless instruction.class == should
|
||||
index += 1
|
||||
instruction = instruction.next
|
||||
end while( instruction )
|
||||
nil
|
||||
end
|
||||
def should( all )
|
||||
#preamble.each {all.shift}
|
||||
#postamble.each {all.pop}
|
||||
str = all.to_s.gsub("Risc::","")
|
||||
ret = ""
|
||||
str.split(",").each_slice(6).each do |line|
|
||||
ret += " " + line.join(",") + " ,\n"
|
||||
end
|
||||
ret
|
||||
end
|
||||
end
|
||||
end
|
112
test/mom/to_risc/test_assignment.rb
Normal file
112
test/mom/to_risc/test_assignment.rb
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
require_relative 'helper'
|
||||
|
||||
module Risc
|
||||
class TestAssignStatement < MiniTest::Test
|
||||
include Statements
|
||||
|
||||
def test_assign_op
|
||||
Parfait.object_space.get_main.add_local(:r , :Integer)
|
||||
|
||||
@input = "r = 10.mod4"
|
||||
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn]
|
||||
assert_nil msg = check_nil , msg
|
||||
end
|
||||
|
||||
def pest_assign_ivar_notpresent
|
||||
@input =s(:statements, s(:i_assignment, s(:ivar, :r), s(:int, 5)))
|
||||
@expect = []
|
||||
assert_raises{ check_nil }
|
||||
end
|
||||
|
||||
def pest_assign_ivar
|
||||
add_space_field(:r , :Integer)
|
||||
|
||||
@input =s(:statements, s(:i_assignment, s(:ivar, :r), s(:int, 5)))
|
||||
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg ,
|
||||
RegToSlot, Label, FunctionReturn]
|
||||
assert_nil msg = check_nil , msg
|
||||
end
|
||||
|
||||
def pest_assign_local_assign
|
||||
Parfait.object_space.get_main.add_local(:r , :Integer)
|
||||
|
||||
@input = s(:statements, s(:l_assignment, s(:local, :r), s(:int, 5)))
|
||||
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg ,
|
||||
RegToSlot, Label, FunctionReturn]
|
||||
assert_nil msg = check_nil , msg
|
||||
end
|
||||
|
||||
def pest_assign_call
|
||||
Parfait.object_space.get_main.add_local(:r , :Object)
|
||||
@input = s(:statements, s(:l_assignment, s(:local, :r), s(:call, :main, s(:arguments))))
|
||||
@expect = [Label, SlotToReg, SlotToReg, RegToSlot, LoadConstant, RegToSlot ,
|
||||
LoadConstant, SlotToReg, RegToSlot, LoadConstant, RegToSlot, RiscTransfer ,
|
||||
FunctionCall, Label, RiscTransfer, SlotToReg, SlotToReg, SlotToReg ,
|
||||
RegToSlot, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn]
|
||||
assert_nil msg = check_nil , msg
|
||||
end
|
||||
|
||||
def pest_named_list_get
|
||||
Parfait.object_space.get_main.add_local(:r , :Integer)
|
||||
@input = s(:statements, s(:l_assignment, s(:local, :r), s(:int, 5)), s(:return, s(:local, :r)))
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, SlotToReg, SlotToReg ,
|
||||
RegToSlot, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn]
|
||||
was = check_return
|
||||
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 pest_assign_local_int
|
||||
Parfait.object_space.get_main.add_local(:r , :Integer)
|
||||
@input = s(:statements, s(:l_assignment, s(:local, :r), s(:int, 5)) )
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg ,
|
||||
RegToSlot, Label, FunctionReturn]
|
||||
was = check_return
|
||||
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 pest_misassign_local
|
||||
Parfait.object_space.get_main.add_local(:r , :Integer)
|
||||
@input = s(:statements, s(:l_assignment, s(:local, :r), s(:string, "5")) )
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn]
|
||||
assert_raises {check }
|
||||
end
|
||||
|
||||
def pest_assign_arg
|
||||
Parfait.object_space.get_main.add_argument(:blar , :Integer)
|
||||
@input = s(:statements, s(:a_assignment, s(:arg, :blar), s(:int, 5)))
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, LoadConstant, SlotToReg ,
|
||||
RegToSlot, Label, FunctionReturn]
|
||||
was = check_return
|
||||
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 pest_misassign_arg
|
||||
Parfait.object_space.get_main.add_argument(:blar , :Integer)
|
||||
@input = s(:statements, s(:a_assignment, s(:arg, :blar), s(:string, "5")))
|
||||
@expect = [Label, LoadConstant, SlotToReg, RegToSlot, Label, FunctionReturn]
|
||||
assert_raises {check }
|
||||
end
|
||||
|
||||
def pest_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(:arg, :balr)))
|
||||
@expect = [Label, SlotToReg, SlotToReg, RegToSlot, LoadConstant, SlotToReg ,
|
||||
RegToSlot, Label, FunctionReturn]
|
||||
was = check_return
|
||||
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
|
@ -16,12 +16,12 @@ module Vool
|
||||
end
|
||||
|
||||
def test_compile_class_one
|
||||
itest = compile_in_test "def meth; @ivar; end"
|
||||
itest = compile_in_test "def meth; @ivar = 5; end"
|
||||
assert itest.instance_type.names.include?(:ivar) , itest.instance_type.names.inspect
|
||||
end
|
||||
|
||||
def test_compile_class_two
|
||||
itest = compile_in_test "def meth; @ivar; end;def meth2(arg); @trivar = 5; end"
|
||||
itest = compile_in_test "def meth; @ivar = 5; end;def meth2(arg); @trivar = 5; end"
|
||||
assert itest.instance_type.names.include?(:trivar) , itest.instance_type.names.inspect
|
||||
end
|
||||
|
||||
@ -33,7 +33,7 @@ module Vool
|
||||
end
|
||||
|
||||
def test_class_body_is_scope
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar ;end")
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar = 5 ;end")
|
||||
assert_equal ScopeStatement , clazz.body.class
|
||||
end
|
||||
|
||||
|
@ -9,7 +9,7 @@ module Vool
|
||||
end
|
||||
|
||||
def create_method
|
||||
VoolCompiler.ruby_to_vool in_Test("def meth; @ivar ;end")
|
||||
VoolCompiler.ruby_to_vool in_Test("def meth; @ivar = 5;end")
|
||||
test = Parfait.object_space.get_class_by_name(:Test)
|
||||
test.get_method(:meth)
|
||||
end
|
||||
@ -17,7 +17,7 @@ module Vool
|
||||
def test_method_has_source
|
||||
method = create_method
|
||||
assert_equal ScopeStatement , method.source.class
|
||||
assert_equal InstanceVariable , method.source.statements.first.class
|
||||
assert_equal IvarAssignment , method.source.statements.first.class
|
||||
end
|
||||
|
||||
def test_method_has_no_locals
|
||||
@ -36,24 +36,23 @@ module Vool
|
||||
assert_equal Parfait::VoolMethod , method.class
|
||||
end
|
||||
|
||||
|
||||
def test_creates_method_statement_in_class
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar ;end")
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar = 5 ;end")
|
||||
assert_equal MethodStatement , clazz.body.statements.first.class
|
||||
end
|
||||
|
||||
def test_parfait_class_creation
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar ;end")
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar = 5;end")
|
||||
assert_equal Parfait::Class , clazz.body.statements.first.clazz.class
|
||||
end
|
||||
|
||||
def test_method_statement_has_class
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar ;end")
|
||||
clazz = VoolCompiler.ruby_to_vool in_Test("def meth; @ivar = 5;end")
|
||||
assert clazz.body.statements.first.clazz
|
||||
end
|
||||
|
||||
def test_method_statement_has_class_in_main
|
||||
clazz = VoolCompiler.ruby_to_vool as_main("def meth; @ivar ;end")
|
||||
clazz = VoolCompiler.ruby_to_vool as_main("def meth; @ivar = 5;end")
|
||||
assert clazz.body.statements.first.clazz
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user