From 3702411043b2e819e5dfffa3c012cf25869f4de3 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Thu, 15 Mar 2018 12:46:56 +0530 Subject: [PATCH] first propper hoisting test had to change course, normalising and object creation is not possible in one go have to now generate random tmp vars that will have to be picked up later (sorted by tmp_ prefix?) --- lib/common/statements.rb | 1 + lib/vool/statement.rb | 29 ++---- lib/vool/statements/assign_statement.rb | 6 +- lib/vool/statements/basic_values.rb | 4 +- lib/vool/statements/class_statement.rb | 10 +- lib/vool/statements/if_statement.rb | 8 +- lib/vool/statements/method_statement.rb | 15 ++- lib/vool/statements/normalizer.rb | 6 +- lib/vool/vool_compiler.rb | 4 +- .../ruby_compiler/test_class_statement.rb | 5 +- .../ruby_compiler/test_method_statement.rb | 4 +- test/vool/vool_compiler/helper.rb | 16 ++++ test/vool/vool_compiler/test_if_statement.rb | 95 +++++++++++++++++++ 13 files changed, 149 insertions(+), 54 deletions(-) create mode 100644 test/vool/vool_compiler/helper.rb create mode 100644 test/vool/vool_compiler/test_if_statement.rb diff --git a/lib/common/statements.rb b/lib/common/statements.rb index 87176bcc..8ee86e21 100644 --- a/lib/common/statements.rb +++ b/lib/common/statements.rb @@ -26,6 +26,7 @@ module Common end def <<(o) @statements << o + self end def collect(arr) @statements.each { |s| s.collect(arr) } diff --git a/lib/vool/statement.rb b/lib/vool/statement.rb index 5d4fb587..4dbf6f02 100644 --- a/lib/vool/statement.rb +++ b/lib/vool/statement.rb @@ -27,13 +27,12 @@ module Vool # after creation vool normalizes to ensure valid syntax and simplify # also throw errors if violation - def normalize(method) - return self + def normalize() + raise self.class.name end - # flatten tree to array - def collect(arr) - arr << self + def each() + yield self end def to_mom( _ ) @@ -44,25 +43,15 @@ module Vool def ct_type nil end - # create corresponding parfait objects, ie classes, types, methods - # mainly implemented by class/method statement - def create_objects - end - # used to collect type information - def add_ivar( array ) - end - - # used to collect frame information - def add_local( array ) - end - - # used for method creation - def set_class( clazz ) - end end class Expression + + def normalize + raise "should not be normalized #{self}" + end + end end diff --git a/lib/vool/statements/assign_statement.rb b/lib/vool/statements/assign_statement.rb index 0311770a..fd456eb1 100644 --- a/lib/vool/statements/assign_statement.rb +++ b/lib/vool/statements/assign_statement.rb @@ -7,9 +7,9 @@ module Vool end def normalize() - raise "not named left #{name}" unless @name.is_a?(Named) - raise "unsupported right #{value}" unless @name.is_a?(Named) or - @name.is_a?(SendStatement) or @name.is_a?(Constant) + raise "not named left #{name.class}" unless @name.is_a?(Symbol) + raise "unsupported right #{value}" unless @value.is_a?(Named) or + @value.is_a?(SendStatement) or @value.is_a?(Constant) self end diff --git a/lib/vool/statements/basic_values.rb b/lib/vool/statements/basic_values.rb index 9b428c02..d50ab179 100644 --- a/lib/vool/statements/basic_values.rb +++ b/lib/vool/statements/basic_values.rb @@ -48,10 +48,8 @@ module Vool end class SelfExpression < Expression attr_reader :clazz - def set_class(clazz) - @clazz = clazz - end def to_mom(in_method) + @clazz = in_method.clazz Mom::SlotDefinition.new(:message , [:receiver]) end def ct_type diff --git a/lib/vool/statements/class_statement.rb b/lib/vool/statements/class_statement.rb index 9506c6c5..cb1e8d3f 100644 --- a/lib/vool/statements/class_statement.rb +++ b/lib/vool/statements/class_statement.rb @@ -5,12 +5,12 @@ module Vool def initialize( name , supe , body) @name , @super_class_name , @body = name , supe , body - unless( body.is_a?(ScopeStatement)) - @body = ScopeStatement.new([]) - @body.statements << body if body - end + @body = ScopeStatement.new([]) unless body end + def normalize + ClassStatement.new(@name , @super_class_name, @body.normalize ) + end # compilation to the next layer, mom # context coming in for class is nil, also for methods, henceafter a method is passed down def to_mom( _ ) @@ -18,7 +18,7 @@ module Vool Mom::Statements.new(methods) end - def collect(arr) + def each() @body.collect(arr) super end diff --git a/lib/vool/statements/if_statement.rb b/lib/vool/statements/if_statement.rb index 4c6fdb92..5d9c2ea0 100644 --- a/lib/vool/statements/if_statement.rb +++ b/lib/vool/statements/if_statement.rb @@ -12,10 +12,10 @@ module Vool simplify_condition end - def normalize(method) - cond , rest = *normalize_name(@condition, method) - fals = @if_false ? @if_false.normalize(method) : nil - me = IfStatement.new(cond , @if_true.normalize(method), fals) + def normalize + cond , rest = *normalize_name(@condition) + fals = @if_false ? @if_false.normalize : nil + me = IfStatement.new(cond , @if_true.normalize, fals) return me unless rest rest << me end diff --git a/lib/vool/statements/method_statement.rb b/lib/vool/statements/method_statement.rb index 366e8549..b62f1c59 100644 --- a/lib/vool/statements/method_statement.rb +++ b/lib/vool/statements/method_statement.rb @@ -2,13 +2,10 @@ module Vool class MethodStatement < Statement attr_reader :name, :args , :body , :clazz - def initialize( name , args , body) + def initialize( name , args , body , clazz = nil) @name , @args , @body = name , args , body - unless( body.is_a?(ScopeStatement)) - @body = ScopeStatement.new([]) - @body.statements << body if body - end - + @body = ScopeStatement.new([]) unless body + @clazz = clazz end # compile to mom instructions. methods themselves do no result in instructions (yet) @@ -24,8 +21,8 @@ module Vool super end - def set_class(clazz) - @clazz = clazz + def normalize + MethodStatement.new( @name , @args , @body.normalize) end def create_objects @@ -50,7 +47,7 @@ module Vool def make_frame type_hash = {} vars = [] - @body.collect([]).each { |node| node.add_local(vars) } + @body.each([]).each { |node| node.add_local(vars) } vars.each { |var| type_hash[var] = :Object } Parfait::NamedList.type_for( type_hash ) end diff --git a/lib/vool/statements/normalizer.rb b/lib/vool/statements/normalizer.rb index e6e73949..d9da815e 100644 --- a/lib/vool/statements/normalizer.rb +++ b/lib/vool/statements/normalizer.rb @@ -6,10 +6,10 @@ module Vool # # eg if( @var % 5) is not normalized # but if(tmp_123) is with tmp_123 = @var % 5 hoited above the if - def normalize_name( condition , method ) + def normalize_name( condition ) return [condition] if condition.is_a?(Named) - local = method.create_tmp - assign = LocalAssignment.new( local , condition) + local = "tmp_#{object_id}" + assign = Statements.new [LocalAssignment.new( local , condition)] [LocalVariable.new(local) , assign] end end diff --git a/lib/vool/vool_compiler.rb b/lib/vool/vool_compiler.rb index cffac6c5..ab5cee34 100644 --- a/lib/vool/vool_compiler.rb +++ b/lib/vool/vool_compiler.rb @@ -5,8 +5,8 @@ module Vool def self.ruby_to_vool( ruby_source ) statements = RubyCompiler.compile( ruby_source ) - statements = statements.normalize(nil) - statements.create_objects + statements = statements.normalize + #statements.create_objects statements end def self.ruby_to_mom(source) diff --git a/test/vool/ruby_compiler/test_class_statement.rb b/test/vool/ruby_compiler/test_class_statement.rb index ed2982bb..39d4b480 100644 --- a/test/vool/ruby_compiler/test_class_statement.rb +++ b/test/vool/ruby_compiler/test_class_statement.rb @@ -30,9 +30,8 @@ module Vool include CompilerHelper def test_compile_one_method - lst = RubyCompiler.compile( in_Test("@ivar") ) - assert_equal ScopeStatement , lst.body.class - assert_equal InstanceVariable , lst.body.statements.first.class + lst = RubyCompiler.compile( in_Test("@ivar = 4") ) + assert_equal IvarAssignment , lst.body.class end def test_compile_two_methods lst = RubyCompiler.compile( in_Test("false; true;") ) diff --git a/test/vool/ruby_compiler/test_method_statement.rb b/test/vool/ruby_compiler/test_method_statement.rb index 50bdf7af..8a774ae7 100644 --- a/test/vool/ruby_compiler/test_method_statement.rb +++ b/test/vool/ruby_compiler/test_method_statement.rb @@ -27,9 +27,9 @@ module Vool assert_equal 2 , @lst.body.length end def test_body_is_scope_one_statement - input = "def tryout(arg1, arg2) ; true ; end " + input = "def tryout(arg1, arg2) ; a = true ; end " lst = RubyCompiler.compile( input ) - assert_equal ScopeStatement , lst.body.class + assert_equal LocalAssignment , lst.body.class end def test_body_is_scope_zero_statement input = "def tryout(arg1, arg2) ; ; end " diff --git a/test/vool/vool_compiler/helper.rb b/test/vool/vool_compiler/helper.rb new file mode 100644 index 00000000..b1ecd5e1 --- /dev/null +++ b/test/vool/vool_compiler/helper.rb @@ -0,0 +1,16 @@ +require_relative "../helper" + +module VoolHelper + include CompilerHelper + + def compile_main( input ) + st = Vool::VoolCompiler.ruby_to_vool as_test_main( input ) + assert_equal st.class , Vool::ClassStatement + assert_equal st.body.class , Vool::MethodStatement + st.body.body + end + + def compile_plain( input ) + Vool::VoolCompiler.ruby_to_vool input + end +end diff --git a/test/vool/vool_compiler/test_if_statement.rb b/test/vool/vool_compiler/test_if_statement.rb new file mode 100644 index 00000000..fdcfe2ea --- /dev/null +++ b/test/vool/vool_compiler/test_if_statement.rb @@ -0,0 +1,95 @@ +require_relative 'helper' + +module Vool + module VoolC + class TestIfStatement < MiniTest::Test + include VoolHelper + + def basic_if + "if(10 < 12) ; a = true ; end" + end + def test_if_basic_hoist + lst = compile_main( basic_if ) + assert_equal Statements , lst.class + assert_equal IfStatement , lst.statements[1].class + end + def pest_if_basic_cond + lst = RubyCompiler.compile( basic_if ) + assert_equal SendStatement , lst.condition.class + end + def pest_if_basic_branches + lst = RubyCompiler.compile( basic_if ) + assert_equal TrueConstant , lst.if_true.class + assert_nil lst.if_false + end + + def double_if + "if(false) ; true ; else ; false; end" + end + def pest_if_double + lst = RubyCompiler.compile( double_if ) + assert_equal IfStatement , lst.class + end + def pest_if_double_cond + lst = RubyCompiler.compile( double_if ) + assert_equal FalseConstant , lst.condition.class + end + def pest_if_double_branches + lst = RubyCompiler.compile( double_if ) + assert_equal TrueConstant , lst.if_true.class + assert_equal FalseConstant, lst.if_false.class + end + + def reverse_if + "true if(false)" + end + def pest_if_reverse + lst = RubyCompiler.compile( reverse_if ) + assert_equal IfStatement , lst.class + end + def pest_if_reverse_cond + lst = RubyCompiler.compile( reverse_if ) + assert_equal FalseConstant , lst.condition.class + end + def pest_if_reverse_branches + lst = RubyCompiler.compile( reverse_if ) + assert_equal TrueConstant , lst.if_true.class + assert_nil lst.if_false + end + + def reverse_unless + "true unless(false)" + end + def pest_if_reverse + lst = RubyCompiler.compile( reverse_unless ) + assert_equal IfStatement , lst.class + end + def pest_if_reverse_cond + lst = RubyCompiler.compile( reverse_unless ) + assert_equal FalseConstant , lst.condition.class + end + def pest_if_reverse_branches + lst = RubyCompiler.compile( reverse_unless ) + assert_nil lst.if_true + assert_equal TrueConstant ,lst.if_false.class + end + + def ternary + "false ? true : false" + end + def pest_if_ternary + lst = RubyCompiler.compile( ternary ) + assert_equal IfStatement , lst.class + end + def pest_if_ternary_cond + lst = RubyCompiler.compile( ternary ) + assert_equal FalseConstant , lst.condition.class + end + def pest_if_ternary_branches + lst = RubyCompiler.compile( ternary ) + assert_equal TrueConstant , lst.if_true.class + assert_equal FalseConstant, lst.if_false.class + end + end + end +end