kObject

@interface kObject 
{
  kClass isa;
}

+ (void)initialize;

+ (kObj)new;

+ (kObj)alloc;
- (void)dealloc;

- (kObj)init;

- (kObj)self;

+ (kClass)class;
- (kClass)class;
+ (kClass)superClass;
- (kClass)superClass;

+ (const_string)className;
- (const_string)className;

- (kObj)copy;

- (kBool*)isEqual:(kObj)obj;

- (uint)hash;

+ (kBool*)isClass:(kClass)c;
- (kBool*)isClass:(kClass)c;
+ (kBool*)isClassNamed:(const string)c;
- (kBool*)isClassNamed:(const string)c;
+ (kBool*)isSubclass:(kClass)c;
- (kBool*)isSubclass:(kClass)c;
+ (kBool*)isSubclassNamed:(const string)c;
- (kBool*)isSubclassNamed:(const string)c;

+ (kBool*)conformsToProtocol:(kProtocol*)p;
- (kBool*)conformsToProtocol:(kProtocol*)p;

- (void)subclassResponsibility:(kSel)s;
- (void)notImplemented:(kSel)s;
- (void)shouldNotImplement:(kSel)s;
- (void)doesNotRecognize:(kSel)s;

- (kObj)perform:(kSel)s;
- (kObj)perform:(kSel)s with:(kObj)o;
- (kObj)perform:(kSel)s with:(kObj)o1 with:(kObj)o2;
- (kObj)perform:(kSel)s with:(kObj)o1 with:(kObj)o2 with:(kObj)o3;

- (kObj)forward:(kSel)s :(kArgs)args;

+ (kBool*)respondsToSelector:(kSel)s;
- (kBool*)respondsToSelector:(kSel)s;

+ (kMethod)methodForSelector:(kSel)s;
- (kMethod)methodForSelector:(kSel)s;

@end
@implementation kObject

+ (void)initialize
{

}

+ (kObj)new
{
  return [[self alloc] init];
}

+ (kObj)alloc
{
  return class_createInstance(self, 0);
}

- (void)dealloc
{
  if(self != null)
    object_dispose(self);
}

- (kObj)init
{
  return self;
}

- (kObj)self
{
  return self;
}

+ (kClass)class
{
  return self;
}

- (kClass)class
{
  return object_getClass(self);
}

+ (kClass)superClass
{
  return class_getSuperclass(self);
}

- (kClass)superClass
{
  return class_getSuperclass(object_getClass(self));
}

+ (const_string)className
{
  return object_getClassName(self);
}

- (const_string)className
{
  return object_getClassName(object_getClass(self));
}

- (kObj)copy
{
  return self;
}

- (kBool*)isEqual:(kObj)obj
{
  if(self == obj)
    return [kBool yes];
  else
    return [kBool no];
}

- (uint)hash
{
  return ((uintptr_t)self >> 3);
}

+ (kBool*)isClass:(kClass)c
{
  if(c == self)
    return [kBool yes];
  else
    return [kBool no];
}

- (kBool*)isClass:(kClass)c
{
  if(c == object_getClass(self))
    return [kBool yes];
  else
    return [kBool no];
}

+ (kBool*)isClassNamed:(const string)c
{
  kClass classNamedC = objc_lookUpClass(c);

  if(classNamedC == null)
    return [kBool no];
  else
    if(self == classNamedC)
      return [kBool yes];
    else
      return [kBool no];
}

- (kBool*)isClassNamed:(const string)c
{
  kClass classNamedC = objc_lookUpClass(c);

  if(classNamedC == null)
    return [kBool no];
  else
    if(object_getClass(self) == classNamedC)
      return [kBool yes];
    else
      return [kBool no];
}

+ (kBool*)isSubclass:(kClass)c
{
  kClass cl;

  for(cl = self; cl != null; cl = class_getSuperclass(cl))
    if(cl == c)
      return [kBool yes];

  return [kBool no];
}

- (kBool*)isSubclass:(kClass)c
{
  kClass cl;

  for(cl = object_getClass(self); cl != null; cl = class_getSuperclass(cl))
    if(cl == c)
      return [kBool yes];

  return [kBool no];
}

+ (kBool*)isSubclassNamed:(const string)c
{
  kClass classNamedC = objc_lookUpClass(c);

  if(classNamedC == null)
    return [kBool no];
  else
  {
    kClass cl;

    for(cl = self; cl != null; cl = class_getSuperclass(cl))
      if(cl == classNamedC)
        return [kBool yes];

    return [kBool no];
  }
}

- (kBool*)isSubclassNamed:(const string)c
{
  kClass classNamedC = objc_lookUpClass(c);

  if(classNamedC == null)
    return [kBool no];
  else
  {
    kClass cl;

    for(cl = object_getClass(self); cl != null; cl = class_getSuperclass(cl))
      if(cl == classNamedC)
        return [kBool yes];

    return [kBool no];
  }
}

+ (kBool*)conformsToProtocol:(kProtocol*)p
{
  kClass c;

  for(c = self; c != null; c = class_getSuperclass(c))
    if(class_conformsToProtocol(c, p))
      return [kBool yes];

  return [kBool no];
}

- (kBool*)conformsToProtocol:(kProtocol*)p
{
  return [[self class] conformsToProtocol:p];
}

- (void)subclassResponsibility:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject-subclassResponsibility:] Invalid selector '%s'!\n", sel_getName(s)];
  else
    [kException raise:@"[kObject-subclassResponsibility:] Selector '%s' should be implemented by subclasses!\n", sel_getName(s)];
}

- (void)notImplemented:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject-notImplemented:] Invalid selector '%s'!\n", sel_getName(s)];
  else
    [kException raise:@"[kObject-notImplemented:] Selector '%s' is not implemented!\n", sel_getName(s)];
}

- (void)shouldNotImplement:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject-shouldNotImplement:] Invalid selector '%s'!\n", sel_getName(s)];
  else
    [kException raise:@"[kObject-shouldNotImplement:] Selector '%s' should not be implemented!\n", sel_getName(s)];
}

- (void)doesNotRecognize:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject-doesNotRecognize:] Invalid selector '%s'!\n", sel_getName(s)];
  else
    [kException raise:@"[kObject-doesNotRecognize:] Selector '%s' is not recognized!\n", sel_getName(s)];
}

- (kObj)perform:(kSel)s
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject-perform:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(object_getClass(self), s);
  if(!msg)
    [kException raise:@"[kObject-perform:] Invalid selector '%s'!\n", sel_getName(s)];

  return (*msg)(self, s);
}

- (kObj)perform:(kSel)s with:(kObj)o
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject-perform:with:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(object_getClass(self), s);
  if(!msg)
    [kException raise:@"[kObject-perform:with:] Invalid selector '%s'!\n", sel_getName(s)];

  return (*msg)(self, s, o);
}

- (kObj)perform:(kSel)s with:(kObj)o1 with:(kObj)o2
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject-perform:with:with:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(object_getClass(self), s);
  if(!msg)
    [kException raise:@"[kObject-perform:with:with:] Invalid selector '%s'!\n", sel_getName(s)];

  return (*msg)(self, s, o1, o2);
}

- (kObj)perform:(kSel)s with:(kObj)o1 with:(kObj)o2 with:(kObj)o3
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject-perform:with:with:with:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(object_getClass(self), s);
  if(!msg)
    [kException raise:@"[kObject-perform:with:with:with:] Invalid selector '%s'!\n", sel_getName(s)];

  return (*msg)(self, s, o1, o2, o3);
}

- (kObj)forward:(kSel)s :(kArgs)args
{
  [self doesNotRecognize:s];

  return nil;
}

+ (kBool*)respondsToSelector:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject+respondsToSelector:] Invalid selector '%s'!\n", sel_getName(s)];
  if(class_respondsToSelector(self, s))
    return [kBool yes];
  else
    return [kBool no];
}

- (kBool*)respondsToSelector:(kSel)s
{
  if(s == 0)
    [kException raise:@"[kObject-respondsToSelector:] Invalid selector '%s'!\n", sel_getName(s)];
  if(class_respondsToSelector(object_getClass(self), s))
    return [kBool yes];
  else
    return [kBool no];
}

+ (kMethod)methodForSelector:(kSel)s
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject+methodForSelector:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(self, s);
  if(!msg)
    [kException raise:@"[kObject+methodForSelector:] Invalid selector '%s'!\n", sel_getName(s)];

  return msg;
}

- (kMethod)methodForSelector:(kSel)s
{
  kMethod msg;

  if(s == 0)
    [kException raise:@"[kObject-methodForSelector:] Invalid selector '%s'!\n", sel_getName(s)];
  msg = class_getMethodImplementation(object_getClass(self), s);
  if(!msg)
    [kException raise:@"[kObject-methodForSelector:] Invalid selector '%s'!\n", sel_getName(s)];

  return msg;
}

@end