/* $Id: Object,v 1.1.1.1 2008/11/28 17:57:26 kiesling Exp $ -*-C-*-*/

/*
  This file is part of ctalk.
  Copyright  2005-2008  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

/*
 *   Object methods.  The Object class is defined by default.  All 
 *   other classes are subclasses of Object.  
 */

#ifndef NULL
#define NULL ((void *)0)
#endif

#ifndef MAXLABEL
#define MAXLABEL 256
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE (!(FALSE))
#endif



/* 
 *    value (void) 
 *      Return the object's value instance variable.
 */

Object instanceMethod value (void) {
  OBJECT *val_obj;
  if (!strcmp (__ctalk_self_internal () -> __o_name, "value"))
    return __ctalk_self_internal ();
  val_obj = __ctalkGetInstanceVariable (self, "value", 1);
  return val_obj;
}

/*
 *    className (void)
 *      Return a String containing the class of the receiver.
 *      If an instance variable that contains the class name
 *      exists, return the instance variable.  Create the
 *      instance variable first if it doesn't exist.  The
 *      method uses the C functions instead of other object
 *      methods so the front end doesn't need to worry about 
 *      the order of method definitions.
 */
Object instanceMethod className (void) {

  OBJECT *__classname_instance_object;

  returnObjectClass String;

  /*
   *  TODO - This version still can't use "self" as a 
   *  function argument within a complex constant
   *  expression, so use __ctalk_self_internal ().
   *  Self is okay to use as an argument in a 
   *  standalone function call, as below.
   */
  if ((__classname_instance_object =
       __ctalkGetInstanceVariable (__ctalk_self_internal (), 
				   "_className", FALSE)) != NULL) {
    return __classname_instance_object;
  } else {
    __classname_instance_object = 
      __ctalkCreateObjectInit ("_className", "String", "Character",
			       self -> scope,
			       self -> __o_classname); 

    __ctalkAddInstanceVariable (self, "_className", 
				__classname_instance_object);
    /*
     *  Note that __ctalkAddInstanceVariable creates a 
     *  _copy_ of __classname_instance_object, so 
     *  the method needs to delete the original
     *  object here.
     */
    __ctalkDeleteObject(__classname_instance_object);

    return __ctalkGetInstanceVariable (self, "_className", TRUE);
  }
  methodReturnNULL
}

/*
 *    name (void)
 *      Return the name of the receiver as a String object.
 *      See the comments for className, above.
 */

Object instanceMethod name (void) {

  OBJECT *__name_instance_object;

  returnObjectClass String;

  if ((__name_instance_object =
       __ctalkGetInstanceVariable (__ctalk_self_internal (), 
				   "_name", FALSE)) != NULL) {
    return __name_instance_object;
  } else {
    __name_instance_object = 
      __ctalkCreateObjectInit ("_name", "String", "Character",
			       self -> scope,
			       self -> __o_name); 

    __ctalkAddInstanceVariable (self, "_name", 
				__name_instance_object);
    __ctalkDeleteObject(__name_instance_object);

    return __ctalkGetInstanceVariable (self, "_name", TRUE);
  }
  methodReturnNULL
}

/*
 *    is (char *classname)
 *      Return True of the receiver is a member of class, 
 *      "classNameArg," False otherwise.
 *
 *    TO DO - In the next release, make sure we can use 
 *     "if (strcmp (self class, self name))..., "
 *     and avoid problems with the class library not being
 *     loaded.
 */

Object instanceMethod is (char *classNameArg) {

  returnObjectClass Integer;

  if (self className == classNameArg name) {
    methodReturnTrue
  } else {
    methodReturnFalse
  }
}

/*
 *    addInstanceVariable (char *name, OBJECT *value)
 *      Add an instance variable object "name" to the receiver,
 *      or set an existing variable.
 *
 *    
 */
Object instanceMethod addInstanceVariable (char *name, OBJECT *value) {
  __ctalkAddInstanceVariable (self, __ctalk_to_c_char_ptr (name), value);
  methodReturnSelf
}

/* 
 *   delete (void)
 *   Delete the receiver object.
 */

Object instanceMethod delete (void) {
  __ctalkDeleteObject (self);
  methodReturnNULL
}


/*
 *  Actually only copies the receiver's instance
 *  variables, class and superclass, and 
 *  receiver's value.  Does not set the 
 *  target object's reference count.
 */
#define IS_OBJECT(x) (!memcmp ((void *)x, "OBJECT", 6))

Object instanceMethod copy (Object __targetObject) {
  OBJECT *__self_alias, *__old_alias, *__arg_alias;
  __self_alias = __ctalk_self_internal ();
  __arg_alias = ARG(0);
  __ctalkCopyObject (OBJREF(__self_alias), OBJREF(__old_alias));
  __old_alias -> __o_varentry = __self_alias -> __o_varentry;
  __ctalkDeleteObject (__self_alias);
  __ctalkCopyObject (OBJREF(__arg_alias), OBJREF(__self_alias));
  __objRefCntSet(OBJREF(__self_alias), __arg_alias -> nrefs);
  __ctalkReplaceVarEntry (__old_alias -> __o_varentry,
			  __self_alias);
  __ctalkDeleteObject (__old_alias);
  return __self_alias;
}

Object instanceMethod setReferenceCount (int __nrefs) {
  OBJECT *__self_alias;
  __self_alias = __ctalk_self_internal ();
  __objRefCntSet(OBJREF(__self_alias), 
		 __ctalkToCInteger(ARG(0), 1));
  methodReturnSelf;
}

Object instanceMethod getReferenceCount (void) {
  OBJECT *__self_alias;
  returnObjectClass Integer;
  __self_alias = __ctalk_self_internal ();
  methodReturnInteger (__self_alias -> nrefs);
}
