require 'test/yarvtest'

# test of syntax
class TestSYNTAX < YarvTestBase

  def test_if_unless
    ae %q(if true  then 1 ; end)
    ae %q(if false then 1 ; end)
    ae %q(if true  then 1 ; else; 2; end)
    ae %q(if false then 1 ; else; 2; end)
    ae %q(if true  then   ; elsif true then ; 1 ; end)
    ae %q(if false then   ; elsif true then ; 1 ; end)

    ae %q(unless true  then 1 ; end)
    ae %q(unless false then 1 ; end)
    ae %q(unless true  then 1 ; else; 2; end)
    ae %q(unless false then 1 ; else; 2; end)

    ae %q(1 if true)
    ae %q(1 if false)
    ae %q(1 if nil)
    
    ae %q(1 unless true)
    ae %q(1 unless false)
    ae %q(1 unless nil)
  end

  def test_while_until
    ae %q(
      i = 0
      while i < 10
        i+=1
      end)

    ae %q(
      i = 0
      while i < 10
        i+=1
      end; i)

    ae %q(
      i = 0
      until i > 10
        i+=1
      end)

    ae %q(
      i = 0
      until i > 10
        i+=1
      end; i)

  end

  def test_and
    ae %q(1 && 2 && 3 && 4)
    ae %q(1 && nil && 3 && 4)
    ae %q(1 && 2 && 3 && nil)
    ae %q(1 && 2 && 3 && false)

    ae %q(1 and 2 and 3 and 4)
    ae %q(1 and nil and 3 and 4)
    ae %q(1 and 2 and 3 and nil)
    ae %q(1 and 2 and 3 and false)
  end
  
  def test_or
    ae %q(1 || 2 || 3 || 4)
    ae %q(1 || false || 3 || 4)
    ae %q(nil || 2 || 3 || 4)
    ae %q(false || 2 || 3 || 4)
    ae %q(nil || false || nil || false)

    ae %q(1 or 2 or 3 or 4)
    ae %q(1 or false or 3 or 4)
    ae %q(nil or 2 or 3 or 4)
    ae %q(false or 2 or 3 or 4)
    ae %q(nil or false or nil or false)
  end

  def test_case
    ae %q(
      case 1
      when 2
        :ng
      end)
      
    ae %q(
      case 1
      when 10,20,30
        :ng1
      when 1,2,3
        :ok
      when 100,200,300
        :ng2
      else
        :elseng
      end)
    ae %q(
      case 123
      when 10,20,30
        :ng1
      when 1,2,3
        :ng2
      when 100,200,300
        :ng3
      else
        :elseok
      end
    )
    ae %q(
      case 'test'
      when /testx/
        :ng1
      when /test/
        :ok
      when /tetxx/
        :ng2
      else
        :ng_else
      end
    )

      ae %q(
        case Object.new
        when Object
          :ok
        end
      )

      ae %q(
        case Object
        when Object.new
          :ng
        else
          :ok
        end
      )
  end

  def test_when
    ae %q(
      case
      when 1==2, 2==3
        :ng1
      when false, 4==5
        :ok
      when false
        :ng2
      else
        :elseng
      end)

    ae %q(
      case
      when nil, nil
        :ng1
      when 1,2,3
        :ok
      when false, false
        :ng2
      else
        :elseng
      end)
      
    ae %q(
      case
      when nil
        :ng1
      when false
        :ng2
      else
        :elseok
      end)
    ae %q{
      def test(arg)
        case 1
        when 2
          3
        end
        return arg
      end
      
      test(100)
    }
  end

  def test_flipflop
    ae %q{
      sum = 0
      30.times{|ib|
        if ib % 10 == 0 .. true
          sum += ib
        end
      }
      sum
    }

    ae %q{
      sum = 0
      30.times{|ib|
        if ib % 10 == 0 ... true
          sum += ib
        end
      }
      sum
    }
  end

  def test_defined_vars
    ae %q{
      defined?(nil) + defined?(self) +
        defined?(true) + defined?(false)
    }
    ae %q{
      a = 1
      defined?(a)
    }
    ae %q{
      defined?(@a)
    }
    ae %q{
      @a = 1
      defined?(@a)
    }
    ae %q{
      defined?(@@a)
    }
    ae %q{
      @@a = 1
      defined?(@@a)
    }
    ae %q{
      defined?($a)
    }
    ae %q{
      $a = 1
      defined?($a)
    }
    ae %q{
      defined?(C_definedtest)
    }
    ae %q{
      C_definedtest = 1
      defined?(C_definedtest)
    } do
      remove_const :C_definedtest
    end
    
    ae %q{
      defined?(::C_definedtest)
    }
    ae %q{
      C_definedtest = 1
      defined?(::C_definedtest)
    } do
      remove_const :C_definedtest
    end

    ae %q{
      defined?(C_definedtestA::C_definedtestB::C_definedtestC)
    }
    ae %q{
      class C_definedtestA
        class C_definedtestB
          C_definedtestC = 1
        end
      end
      defined?(C_definedtestA::C_definedtestB::C_definedtestC)
    } do
      remove_const :C_definedtestA
    end
  end

  def test_defined_method
    ae %q{
      defined?(m)
    }
    ae %q{
      def m
      end
      defined?(m)
    }
    
    ae %q{
      defined?(a.class)
    }
    ae %q{
      a = 1
      defined?(a.class)
    }
  end
  
end



