class TestCase::Operator::Isa {
  use TestCase::Minimal;
  use TestCase::Simple;
  use Comparator;
  use Complex_2d;
  use Complex_2f;
  use Point;
  use Stringable;
  use Stringer;
  
  static method isa : int () {
    
    # Numeric
    {
      {
        my $value : byte;
        
        unless ($value isa byte) {
          return 0;
        }
        
        if ($value isa short) {
          return 0;
        }
      }
      
      {
        my $value : double;
        
        unless ($value isa double) {
          return 0;
        }
      }
    }
    
    # Multi-numeric
    {
      {
        my $value : Complex_2d;
        
        unless ($value isa Complex_2d) {
          return 0;
        }
        
        if ($value isa Complex_2f) {
          return 0;
        }
      }
    }
    
    # Ref
    {
      {
        my $value : byte*;
        
        unless ($value isa byte*) {
          return 0;
        }
        
        if ($value isa short*) {
          return 0;
        }
      }
    }
    
    # Any object array
    {
      {
        my $value = new object[0];
        
        unless ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value = (object)new object[0];
        
        unless ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value : object[];
        
        if ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value = new Point[0];
        
        unless ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value = Point->new;
        
        if ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value = new Stringable[0];
        
        unless ($value isa object[]) {
          return 0;
        }
      }
      
      {
        my $value = new int[0];
        
        if ($value isa object[]) {
          return 0;
        }
      }
      
    }
    
    # An object type
    {
      {
        my $value : Point = Point->new;
        
        unless ($value isa Point) {
          return 0;
        }
      }
      
      {
        my $value : Point = Point->new;
        
        unless ($value isa Cloneable) {
          return 0;
        }
      }
      
      {
        my $value : Point;
        
        if ($value isa Point) {
          return 0;
        }
      }
    }
    
    # Interface
    {
      {
        my $point = Point->new;
        
        unless ($point isa Stringable) {
          warn dump $point;
          return 0;
        }
      }
      
      {
        my $anon = method : string ($object : object) {
          
        };
        
        unless ($anon isa Stringer) {
          warn dump $anon;
          return 0;
        }
      }
      
      {
        my $anon = (object)method : string ($object : object) {
          
        };
        
        unless ($anon isa Stringer) {
          warn dump $anon;
          return 0;
        }
      }
    }
    
    return 1;
  }
  
  static method isa_any_object_type : int () {
    
    # Removed
    
    return 1;
  }
  
  static method isa_numeric_type : int () {
    my $num : int;
    
    unless ($num isa int) {
      return 0;
    }
    
    if ($num isa long) {
      return 0;
    }
    
    return 1;
  }
  
  static method isa_multi_numeric_type : int () {
    my $num : Complex_2d;
    
    unless ($num isa Complex_2d) {
      return 0;
    }
    
    if ($num isa Complex_2f) {
      return 0;
    }
    
    return 1;
  }
  
  static method isa_match_class : int () {
    my $minimal = TestCase::Minimal->new;
    if ($minimal isa TestCase::Minimal) {
      my $object : object = $minimal;
      if ($object isa TestCase::Minimal) {
        return 1;
      }
    }
    
    return 0;
  }
  
  static method isa_match_array : int () {
    my $minimals = new TestCase::Minimal[3];
    my $nums = new int[3];
    
    if ($minimals isa TestCase::Minimal[]) {
      if ($nums isa int[]) {
        return 1;
      }
    }
    
    return 0;
  }
  
  static method isa_not_match_class : int () {
    my $minimal = TestCase::Minimal->new;
    if (!($minimal isa TestCase::Simple)) {
      return 1;
    }
    
    return 0;
  }
  
  static method isa_not_match_class_undef : int () {
    my $minimal : TestCase::Minimal = undef;
    
    if (!($minimal isa TestCase::Minimal)) {
      return 1;
    }
    
    return 0;
  }
  
  static method isa_match_callback : int () {
    
    my $comparator = method : int ($object1 : object, $object2 : object) {
      
    };
    if ($comparator isa Comparator) {
      my $object : object = $comparator;
      if ($object isa Comparator) {
        return 1;
      }
    }
    
    return 0;
  }
  
  static method isa_not_match_callback_undef : int () {
    my $comparator : Comparator;
    
    if (!($comparator isa Comparator)) {
      return 1;
    }
    
    return 0;
  }
  
  static method isa_not_match_callback : int () {
    my $minimal : TestCase::Minimal = TestCase::Minimal->new;
    if (!($minimal isa Comparator)) {
      return 1;
    }
    
    return 0;
  }
  
  static method isa_error : int () {
    
    {
      my $error_basic_type_id = basic_type_id Error;
      
      unless ($error_basic_type_id isa_error Error) {
        return 0;
      }
      
      if ($error_basic_type_id isa_error Int) {
        return 0;
      }
    }
    
    {
      my $error_system_basic_type_id = basic_type_id Error::System;
      
      unless ($error_system_basic_type_id isa_error Error) {
        return 0;
      }
      
      unless ($error_system_basic_type_id isa_error Error::System) {
        return 0;
      }
    }
    
    {
      my $error_not_supported_basic_type_id = basic_type_id Error::NotSupported;
      
      unless ($error_not_supported_basic_type_id isa_error Error) {
        return 0;
      }
      
      unless ($error_not_supported_basic_type_id isa_error Error::NotSupported) {
        return 0;
      }
    }
    
    # Extra
    {
      eval { die; }
      
      unless (eval_error_id isa_error Error) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }
  
  static method isa_extra : int () {
    
    # Assignability cached
    {
      my $object = Int->new(1);
      
      # True first
      unless ($object isa Int) {
        return 0;
      }
      
      # True second
      unless ($object isa Int) {
        return 0;
      }
      
      # False first
      if ($object isa Short) {
        return 0;
      }
      
      # False second
      if ($object isa Short) {
        return 0;
      }
    }
    
    $@ = undef;
    
    return 1;
  }
}