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