diff --git a/lib/ruby/class_method_statement.rb b/lib/ruby/class_method_statement.rb index 93ea89cd..753d718f 100644 --- a/lib/ruby/class_method_statement.rb +++ b/lib/ruby/class_method_statement.rb @@ -2,7 +2,7 @@ module Ruby class ClassMethodStatement < MethodStatement def to_vool -# Vool::ClassMethodStatement.new( @name , @args.dup , @body.to_vool) + Vool::ClassMethodStatement.new( @name , @args.dup , @body.to_vool) end def to_s(depth = 0) diff --git a/lib/vool/class_method_statement.rb b/lib/vool/class_method_statement.rb new file mode 100644 index 00000000..d7a8aaf0 --- /dev/null +++ b/lib/vool/class_method_statement.rb @@ -0,0 +1,58 @@ +module Vool + class ClassMethodStatement < Statement + attr_reader :name, :args , :body + + def initialize( name , args , body ) + @name , @args , @body = name , args , body + raise "no bod" unless @body + end + + def to_mom(clazz) + raise( "no class in #{self}") unless clazz + method = clazz.add_method_for(name , make_arg_type , make_frame , body ) + compiler = method.compiler_for(clazz.instance_type) + each {|node| raise "Blocks not implemented" if node.is_a?(BlockStatement)} + compiler + end + + def each(&block) + block.call(self) + @body.each(&block) + end + + def has_yield? + each{|statement| return true if statement.is_a?(YieldStatement)} + return false + end + + def make_arg_type( ) + type_hash = {} + @args.each {|arg| type_hash[arg] = :Object } + type_hash[:implicit_block] = :Block if has_yield? + Parfait::NamedList.type_for( type_hash ) + end + + def to_s(depth = 0) + arg_str = @args.collect{|a| a.to_s}.join(', ') + at_depth(depth , "def #{name}(#{arg_str})" , @body.to_s(depth + 1) , "end") + end + + private + + def make_frame + nodes = [] + @body.each { |node| nodes << node } + nodes.dup.each do |node| + next unless node.is_a?(BlockStatement) + node.each {|block_scope| nodes.delete(block_scope)} + end + type_hash = {} + nodes.each do |node| + next unless node.is_a?(LocalVariable) or node.is_a?(LocalAssignment) + type_hash[node.name] = :Object + end + Parfait::NamedList.type_for( type_hash ) + end + + end +end diff --git a/lib/vool/statement.rb b/lib/vool/statement.rb index 33a49b45..38d2b4ec 100644 --- a/lib/vool/statement.rb +++ b/lib/vool/statement.rb @@ -70,6 +70,7 @@ require_relative "if_statement" require_relative "ivar_assignment" require_relative "local_assignment" require_relative "method_statement" +require_relative "class_method_statement" require_relative "return_statement" require_relative "statements" require_relative "send_statement" diff --git a/test/ruby/test_class_method_statement.rb b/test/ruby/test_class_method_statement.rb new file mode 100644 index 00000000..ce7182d8 --- /dev/null +++ b/test/ruby/test_class_method_statement.rb @@ -0,0 +1,71 @@ +require_relative "helper" + +module Ruby + class TestClassMethodStatement < MiniTest::Test + include RubyTests + + def test_basic_method + input = "def self.tryout() ; return true ; end " + @lst = compile( input ) + assert_equal Ruby::ClassMethodStatement , @lst.class + end + def test_method_arg + input = "def self.tryout(arg) ; arg = true ; return arg ; end " + @lst = compile( input ) + assert_equal Ruby::ClassMethodStatement , @lst.class + end + end + class TestClassMethodStatement2 < MiniTest::Test + include RubyTests + def test_body_is_scope_one_statement + input = "def self.tryout(arg1, arg2) ; a = true ; end " + lst = compile( input ) + assert_equal LocalAssignment , lst.body.class + end + def test_body_is_scope_zero_statement + input = "def self.tryout(arg1, arg2) ; arg1 = arg2 ; end " + lst = compile( input ) + assert_equal LocalAssignment , lst.body.class + end + end + + class TestClassMethodStatementTrans < MiniTest::Test + include RubyTests + + def setup() + input = "def self.tryout(arg1, arg2) ; a = arg1 ; end " + @lst = compile( input ).to_vool + end + def test_method + assert_equal Vool::ClassMethodStatement , @lst.class + end + def test_method_args + assert_equal [:arg1, :arg2] , @lst.args + end + def test_body_is_scope_zero_statement + assert_equal Vool::LocalAssignment , @lst.body.class + end + end + class TestClassMethodStatement < MiniTest::Test + include RubyTests + + def setup() + input = "def self.tryout(arg1, arg2) ; true ; false ; end " + @lst = compile( input ) + end + def test_method + assert_equal ClassMethodStatement , @lst.class + end + + def test_method_name + assert_equal :tryout , @lst.name + end + def test_method_args + assert_equal [:arg1, :arg2] , @lst.args + end + def test_basic_body + assert_equal ScopeStatement , @lst.body.class + assert_equal 2 , @lst.body.length + end + end +end diff --git a/test/ruby/test_method_statement.rb b/test/ruby/test_method_statement.rb index 035878a1..1818a86f 100644 --- a/test/ruby/test_method_statement.rb +++ b/test/ruby/test_method_statement.rb @@ -1,23 +1,6 @@ require_relative "helper" module Ruby - class TestMethodStatementTrans < MiniTest::Test - include RubyTests - - def setup() - input = "def tryout(arg1, arg2) ; a = arg1 ; end " - @lst = compile( input ).to_vool - end - def test_method - assert_equal Vool::MethodStatement , @lst.class - end - def test_method_args - assert_equal [:arg1, :arg2] , @lst.args - end - def test_body_is_scope_zero_statement - assert_equal Vool::LocalAssignment , @lst.body.class - end - end class TestMethodStatement < MiniTest::Test include RubyTests @@ -53,18 +36,21 @@ module Ruby assert_equal LocalAssignment , lst.body.class end end - class TestClassMethodStatement < MiniTest::Test - include RubyTests - def test_basic_method - input = "def self.tryout() ; return true ; end " - @lst = compile( input ) - assert_equal Ruby::ClassMethodStatement , @lst.class + class TestMethodStatementTrans < MiniTest::Test + include RubyTests + def setup() + input = "def tryout(arg1, arg2) ; a = arg1 ; end " + @lst = compile( input ).to_vool end - def test_method_arg - input = "def self.tryout(arg) ; arg = true ; return arg ; end " - @lst = compile( input ) - assert_equal Ruby::ClassMethodStatement , @lst.class + def test_method + assert_equal Vool::MethodStatement , @lst.class + end + def test_method_args + assert_equal [:arg1, :arg2] , @lst.args + end + def test_body_is_scope_zero_statement + assert_equal Vool::LocalAssignment , @lst.body.class end end end